Uses of Final Keyword

Author: Ron Lancaster 
Date: August 27th, 2005

The final keyword can be a powerful ally in the ongoing battle against coding errors. - Luke Skywalker

Overview

Generally, the final keyword is underutilized by Java developers. When used correctly, the keyword can prevent coding errors and improve code quality.

There are four constructs in which the final keyword in Java is legal. In each case, the final keyword results in a different effect.

  • Variables (and Parameters) - final variables may only be set once.
  • Fields - final fields may only be set once, and must be set during class construction.
  • Classes - final classes cannot be overridden.
  • Methods - final methods cannot be overridden.

Motivation

Declaring variables, fields, and parameters final helps prevent coding errors. In some instances, code complexity is reduced by removing the need for checks for variable initialization. Declaring classes and methods final enforces the intentions of the class designer with respect to extension.

A number of articles on the usage of final refer to performance optimizations made by the compiler. Ignore these! The optimizations vary among compiler versions (including JDK versions of the compiler). Additionally, this is a form of premature optimization ? and as we know, premature optimization is the root of all evil.

Usage

a. Guidelines

  • Variables and fields should be declared final where possible.
  • Method parameters may optionally be declared final. This is optional due to the large codebase that does not follow this convention. However, it is encouraged to do so in new code.
  • Classes not specifically designed to be extended should be declared final.
  • On classes that are designed to be extended, final method declarations can be used to achieve finer control over how they are extended.

b. Final Variables

A final variable is assigned exactly once, either when declared (by an initializer) or at a later time (by assignment). The latter is called a "blank final," and if the compiler cannot guarantee that the blank final will be assigned a value exactly once prior to its first use, it will issue an error message. This prevents reassignment errors and simplifies the code (e.g. removing the need to check for variable initialization).

Note that there are situations where final variables can?t be used. Examples include when certain serialization customizations are used, when a variable has to be initialized prior to a try clause (or other block of code), when initialization cannot occur at construction due to a dependency on system state, etc.

c. Final Parameters

A final parameter cannot be reassigned by the method. Note, see the Caution section below.

d. Final Fields

Final fields may only be assigned once and must be assigned at object construction. This is performed either by an initializer expression, an initialization block, or an assignment in each and every constructor.

e. Final Constants

This is a common idiom used by Java developers signified by a field name in all caps. For example, public static String CONSTANT = "Constant";

f. Enforce Atomicity of Aggregate Objects

Aggregation implies that one object owns or is responsible for another object. The final keyword can help define this constraint by guaranteeing that the object was created in full (including that the aggregation was initialized correctly), or that the object was not created due to exception. For example, if a car must have an engine, then declaring this aggregation final requires the compiler to enforce this relationship.

g. Class Invariants

Class invariants refer to attributes that are true of a class in general. That is, that they are always true. Declaring a field final is an effective way of guaranteeing this. It should be noted that this technique cannot always be used due to the restriction of initializing the invariant at class construction.

Caution

Primitives declared final are immutable. Objects declared final are not immutable ? the final keyword will only protect against reassignment of the reference. Java does not provide a way of declaring an instance of an object as immutable. This caution also applies to arrays and collections - both of which can have their contents modified. To prevent modification of collections, see the Collections.unmodifiableInterface() methods.

Keyword Order

The following keyword order should be used: 
Fields - public, protected, private, static, final, transient, volatile. 
Methods - public, protected, private, abstract, static, final, synchronized, native, strictfp. 
Classes - public, protected, private, abstract, static, final, strictfp.

IDEA

With IDEA 4.5, additional error checking capabilities have been added that include checking for the use of the final keyword. See project properties, Errors. Appropriate settings to meet the coding standard are:

  • Local code analysis - Local variable or parameter can be final - As Warning - Check "Report local variables", optionally "Report method parameters".
  • Class structure - "final" class - Do not show
  • Class structure - "final" method - Do not show
  • Class structure - "final" method in "final" class - As warning
  • Class structure - "private" method declared "final" - As warning
  • Class structure - "protected" member in "final" class - As warning
  • Class structure - "static" method declared "final" - As warning
  • Class structure - "static", non-"final" field - Do not show
  • Probable bugs - Non-final field referenced in "compareTo()" - As error
  • Probable bugs - Non-final field referenced in "equals()" - As error
  • Probable bugs - Non-final field referenced in "hashCode()" - As error
  • Verbose or redundant code constructs - Unnecessary "final" for method parameter - Do not show

References