Quick Tip: Using Final for Local Variables in Java

From Aventine Solutions

Jump to: navigation, search

It is a habit I got into after reading the Martin Fowler book Refactoring: Improving the Design of Existing Code whereby a class of bugs/errors can be avoided from reassignment of local variables.

The argument for this technique is that the programmer declares ahead of time that a local variable will not be changed. The side affect of this is that other programmers who take over maintenance of the same code clearly see the intention. There is an argument against and that is the constant use of final clutters the code when your IDE will probably tell you you're making a destructive reassignment anyway.

Contents

[edit] Example 1

 
public void someFunction(Bean bean) {
    String s = bean.getPropertyValue();
    // lot's of complicated code
    s = "someothervalue";
    // still more logic
    // the reassignment of variable "s" is bad
    // because it is actually being used for some other
    // purpose and has suddenly and probably inadvertently
    // taken on a completely different symantic meaning.
}

... using final, the programmer avoids ahead of time problems in the logic such a reassignment can cause:

public void someFunction(Bean bean) {
    final String s = bean.getPropertyValue();
    // lot's of complicated code
    final String otherVal = "someothervalue";
    // still more logic
}

[edit] Example 2

try {
  // complicated logic
} catch (Exception e) {
  e = new ApplicationException("something went wrong and I'm not telling you");
  LOG.error(e);
  throw e;
  // this is bad because I lost the original information in "e" from reassignment and debugging
  // errors will be harder later
}

... instead ....

try {
  // complicated logic
} catch (final Exception e) {
  final ApplicationException newEx = new ApplicationException("some useful message", e);
  LOG.error(newEX);
  throw newEx;
  // nice!  I avoided clobbering the useful exception information plus I "wrapped" the
  // original exception with my application exception
}

[edit] Example 3

 
public void someFunction(ComplexObject a, ComplexObject b) {
   // logic logic logic
   a = bean.getSomething();
   b = new ComplexObject("new data");
   // bad bad bad ... *never* reassign function parameters
}

... better is ...

public void someFunction(final ComplexObject a, final ComplexObjex b) {
   // now I won't make the accidental mistake of clobbering my nice objects
   // and destroying the intention of this function.
}

[edit] Exceptions to the rule: Iterators

 
for( final i = 0; i < 10; i++ ) {
  // won't run! iterator primitives by their nature can't be final
}
 
for( final String name: myCollection ) {
  // also won't run
}
Personal tools