final fields, final variables & immutability
Assigning exactly once — and what immutability really means.
final: assign exactly once
The final keyword on a variable means it can be written exactly once:
final int MAX = 100; // local: assigned at declaration
final int computed; // blank final local
computed = calculate(); // OK — assigned exactly once
// computed = 5; // compile error — already assigned
For a final instance field, it must be assigned either: - at its declaration site, or - in every constructor.
public class Circle {
private final double radius; // blank final field
Circle(double radius) {
this.radius = radius; // required — and the only assignment allowed
}
}
Immutability goes one level deeper: final on a reference prevents *reassigning the variable*, but the *object it points to* can still be mutated:
final List<String> list = new ArrayList<>();
list.add("hello"); // OK — mutating the object
// list = new ArrayList<>(); // compile error — reassigning the reference
A class is truly immutable (like String) only when all its fields are final AND those fields hold only primitives or references to other immutable objects.