liveBook · Manning

Final

As explained in 100 Java Mistakes and How to Avoid Them

The final modifier is a Java declaration modifier that prevents reassignment of a local variable after its initialization or assignment.

In Java, final can express an intention that a declaration must not change in a particular way. For a local variable, it prevents reassignment after the variable receives its value. That constraint can turn a subtle control-flow error into a compiler error: when a missing else splits what was meant to be one conditional chain, an earlier assignment may be overwritten by a later branch. section 3.1

Make a conditional result single-assignment

When every branch only chooses data for one later operation, assign the result inside the chain and call the operation afterward. Declaring that result final exposes a missing else because more than one branch can then assign data. This is a deliberate trade-off: final locals add visual noise, but are especially useful where a variable is intended to receive exactly one branch result. section 3.1

final Data data;
if (condition1) {
  data = getData1();
} else if (condition2) {
  data = getData2();
} if (condition3) {
  data = getData3();     #1
} else if (condition4) {
  data = getData4();
} else {
  data = getDefaultData();
}
process(data);

A missing else creates two independent paths that can assign data. Because data is final, the second possible assignment is rejected rather than silently overwriting the first. section 3.1

For methods, final can protect required superclass behavior from being replaced by a subclass override. Put the nontrivial standard work in a final method, then call an empty protected hook for customization. A subclass can supply its additional behavior through the hook without needing, or being able to forget, a superclass call that performs essential work. section 3.10

Protect standard key handling

A final onKeyDown method can process standard keys and then call afterKeyDown(event). Subclasses override afterKeyDown rather than onKeyDown, so the standard processing remains in place while extension is still available. section 3.10

Finality also matters when choosing between getClass() and instanceof. getClass() compares an object's exact runtime class, while instanceof accepts subclasses. If the tested class is final, that subclass distinction disappears, apart from null handling; otherwise, decide explicitly whether subclasses should match. Static analysis can flag impossible exact-class tests, but a suspected false warning should be checked with a unit test. section 9.6 section 9.6

How 100 Java Mistakes and How to Avoid Them covers it

How deep it goes
Explains final through conditional assignments, method hooks, and exact-class tests, without a general declaration taxonomy.
Examples
Uses a branch-selected Data value, key-event handling hooks, and Date/Calendar runtime-class conversion.
What it assumes
Assumes familiarity with Java conditionals, local variables, inheritance, and runtime type checks.
What you can do after
Diagnose/debug with it, exposing duplicate conditional assignments and protecting required superclass behavior.
How it connects
Connects final with if–else chains, method overriding, inheritance, getClass(), instanceof, static analysis, and unit tests.

Also explained in

Compare how 3 books explain final →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Java Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.