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


