Declaring Final Variables Elegantly Using The Assigner Design Pattern
A final variable is used to define a constant value and reference, and can only be defined once. In most cases, declaring a final variable is just a matter of assigning to a primitive value or an object reference directly. However, in some cases, declaring a final class/instance variable may be more involving especially it gets assigned from a method that throws an Exception (eg API for database access, web access), or it may involve multiple statements.
Editors Note: This content was submitted by geekycoder
In such cases, the code may become cluttered with class helper methods and dummy temporary variables that help define the final variable, making the code look less elegant and harder to maintain. The following common ways of declaring a final variable in those situations might look familiar to many.
Declaring final variable by instance/class method
Declaring final variable by instance/class variable with static/instance initializer.
The aforementioned ways definitely get the work done but at the cost of elegancy. The helper method and variable help to define the final variable but it inevitably becomes part of class method and variable.
Recommended way: Assigner Design Pattern
A better way to declare final instance/class variable is to use Generic method and interface with the advantages of
- forcing initializing method in the same statement as the final variable declaration.
- reusing as design pattern (term: Assigner Design Pattern) and enhancing code readability
There is generic helper class whose interface and method accept a parametric type similar to the type of final variable. The advantage of using Generics is that the type mismatch will be caught at compile time rather than runtime. This design pattern is termed Assigner because it assigns value to a variable from initializing method.
Using the design pattern, the code becomes cleaner and elegant.
The above can be downloaded - assigner.zip (1kb)
Some will probably argue that Assigner Design Pattern may not be efficient compare to the first two ways since additional bytecode classes are generated for Assigner helper class and inner class. However, like other design patterns, code readability and reusability may outweigh the negligible performance loss and inefficiency.
- Login or register to post comments
- 6000 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)




Comments
Ricky Clarkson replied on Thu, 2010/03/04 - 6:04am
Fab Mars replied on Thu, 2010/03/04 - 7:56am
I don't buy this one. That was a joke right? Elegant...Readability...Reusability...come on!
That's how we end up struggling with our junior developers: just because they're spending all their time implementing every crazy pattern they've seen on the internet instead of focussing on the real useful business code our customers are asking for.
I also second the previous comment regarding exceptions: since the code you're using to assign your final variable can't throw exceptions, you're bound to pretend they will never happen and mask yours somehow (rethrow a RuntimeException which would probably end up killing your program, or use an infamous printstacktrace/log), after which your class won't be correctly initialized anyway... We're all confronted with that.
Alessandro Santini replied on Thu, 2010/03/04 - 9:38am
GeekyCoder coder replied on Thu, 2010/03/04 - 11:14am
Hi, guys.
Of course, there is many ways to accomplish the same thing. Some prefer standardised solution, some prefer their own way. After all, a design pattern is just a pattern. Use whatever you feel comfortable with, and use whatever works for you.
<:^}
GeekyCoder coder replied on Thu, 2010/03/04 - 11:18am
Hi,
What I define is a just standard pattern and whatever you want to put into the body, whether exception handling (good or bad) or laundry cloth will be up to you.
cheers
Rogerio Liesenfeld replied on Thu, 2010/03/04 - 12:18pm
GeekyCoder coder replied on Thu, 2010/03/04 - 2:00pm
in response to: Rogerio Liesenfeld
The pattern can be used in many ways and not just confined to my code example. My code example is just to illustrate one example use of the pattern, which happen to use a class to demonstrate the pattern. I think we should look wider beyond what you just see from the code example.
Hint: How about declaring variable in interface (constructor is out) ? Can this pattern be applied too ? <:^}
public interface IConstant
{
String IDENTIFIER = Assigner.assign(
new Assigner.IAssignable<java.lang.String>()
{
public String initialize()
{
// eg database and web access through API
// that throws exception.
try
{
java.net.URL _url = new java.net.URL(
"http://www.java.com");
return _url.getHost();
}
catch (java.net.MalformedURLException _ex)
{
_ex.printStackTrace();
}
return "error";
}
});
}
As I have mentioned, whether it is a good practice to handle exception this way will be up to individual to decide as it is a matter of preference.
cheers ...
GeekyCoder coder replied on Thu, 2010/03/04 - 2:02pm
Anyway, for those who are interested to read more about final variable
check this out.
http://renaud.waldura.com/doc/java/final-keyword.shtml#many
Rogerio Liesenfeld replied on Thu, 2010/03/04 - 3:40pm
in response to: geekycoder
Ricky Clarkson replied on Fri, 2010/03/05 - 2:30am
Mladen Girazovski replied on Fri, 2010/03/05 - 5:14am
I'm not sure if your post was meant to be taken seriously or if you're taking us for a ride..i'll take the bait.
You don't reale handle the Exception, instead, you're initilaising the variable with "error"... now, how can you call that "Exception Handling"??? You're ignoring it, nothing else.
And no, it is not a matter of personal preference, there is something called best practices for exception handling, which is quite the opposite of what you've showed.
Andreou Dimitris replied on Fri, 2010/03/05 - 7:57am
Rogerio Liesenfeld replied on Fri, 2010/03/05 - 11:53am
in response to: rickyclarkson
final Define it;
ButYouCan() {
Define theValue;
try {
theValue = new Define("this way");
} catch (RuntimeException e) {
theValue = because.definiteAssignment(isForLocalVariablesNotFields);
}
it = theValue;
}
}
Jochen Bedersdorfer replied on Fri, 2010/03/05 - 12:37pm
I am developing in Java for 14 years now, but I never ever had the urge to develop an interface or abstract class for initialization purposes only.
I fail to see reuse or elegance here, I'm afraid.
It is exactly this unnecessary complexity that lets people perceive Java as clumbsy or heavyweight.
Please reconsider using or promoting this pattern.
Thanks!
Till Omann replied on Fri, 2010/03/05 - 2:45pm
Declaring anonymous inner classes is IMO always a critical point. I agree with most software architects to use it the less as possible. I agree that the (default) constructor is the right place for most cases to assign final variables.
The exception handling? As commented above ... ^^
Hopefully closures will soon find their way into Java. Closures are a nice and more readable replacement for the usage of anonymous inner classes and they keep your packages clean from "one method interfaces".
Stephane Vaucher replied on Fri, 2010/03/05 - 6:02pm
public DeclareFinalVariableByAssigner() { this(name()); // NO GOOD... } private DeclareFinalVariableByAssigner(String name) { IDENTIFIER = name; } private String name() { String tmp; try { java.net.URL _url = new java.net.URL("http://www.java.com"); tmp = _url.getHost(); } catch (java.net.MalformedURLException _ex) { _ex.printStackTrace(); tmp= "fpp"; } return tmp; }