Use final liberally

Use the final keyword liberally to communicate your intent.

The final keyword has more than one meaning :

In the last case, "value" for primitives is understood in the usual sense, while "value" for objects means the object's identity, not its state. Once the identity of a final object reference is set, it can still change its state, but not its identity.

Declaring primitive fields as final automatically ensures thread-safety for that field.

Some habitually declare parameters as final, since this almost always the desired behaviour. Others find this verbose, and of little real benefit.

Consistently using final with local variables (when appropriate) can be useful as well. It brings attention to the non-final local variables, which usually have more logic associated with them (for example, result variables, accumulators, loop variables). Many find this verbose. A reasonable approach is to use final for local variables only if there is at least one non-final local variable in the method ; this serves to quickly distinguish the non-final local variables from the others.

Using final :

Example

import java.util.*;
import java.lang.reflect.Field;

/**
* This class cannot be extended.
*/
public final class Boat {

  public Boat( final String aName, final int aLength, final Date aDateManufactured){
    fName = aName;
    fLength = aLength;
    //make a defensive copy of the date
    fDateManufactured = new Date( aDateManufactured.getTime() );

    //does not compile, since argument is final:
    //aDateManufactured = null;
    //does not compile, since argument is final :
    //aLength = 0;
  }

  /**
  * Cannot be overridden, since the class itself is final.
  */
  public void setDate( final Date aNewDate ){
    //even though the field is final, its state can change:
    fDateManufactured.setTime( aNewDate.getTime() );

    //does not compile, since field is final:
    //fDateManufactured = aNewDate;
  }

  /**
  * Suitable only for debugging.
  *
  * All local variables are final except for the loop variable.
  */
  public String toString() {
    final StringBuilder result = new StringBuilder();
    final String newLine = System.getProperty("line.separator");
    result.append( this.getClass().getName() );
    result.append( " Object {" );
    result.append(newLine);

    //get fields declared in this class only (no fields of superclass)
    final List<Field> fields = Arrays.asList(this.getClass().getDeclaredFields());

    //get field names paired with their values
    for ( Field field : fields ) {
      result.append("  ");
      try {
        result.append( field.getName() );
        result.append(": ");
        //requires access to private field:
        result.append( field.get(this) );
      }
      catch ( IllegalAccessException ex ) {
        System.out.println(ex);
      }
      result.append(newLine);
    }
    result.append("}");
    return result.toString();
  }

  //..elided

  /// PRIVATE ////
  private final String fName;
  private final int fLength;
  private final Date fDateManufactured;
} 



See Also :
Immutable objects
Designing for subclassing
Overridable methods need special care
Remember styles of inheritance
Would you use this technique?
Yes   No   Undecided   
© 2013 Hirondelle Systems | Source Code | Contact | License | RSS
Individual code snippets can be used under this BSD license - Last updated on August 30, 2012.
Over 2,400,000 unique IPs last year - Built with WEB4J.
- In Memoriam : Bill Dirani -