The <code>final</code> Keyword in Java
final means "assign exactly once" or "cannot be changed" depending on what it modifies. A final variable can't be reassigned. A final method can't be overridden. A final class can't be subclassed.
Final variables
final int MAX = 100;
MAX = 200; // β compile error
final User u = new User("Alice");
u.setAge(30); // β
the REFERENCE is final, the OBJECT isn't
u = new User("Bob"); // β can't reassign
Crucial distinction: final prevents reassignment of the variable. It does not make the referenced object immutable.
Final fields
public class Order {
private final long id; // assigned once β in the constructor
private final Instant createdAt;
public Order(long id) {
this.id = id;
this.createdAt = Instant.now();
}
}
Always prefer final fields. They make the class thread-safe by accident β a properly constructed object with only final fields is safely visible to every thread without synchronisation.
Final methods β can't be overridden
public class Shape {
public final String id() { return ... } // subclasses must not redefine
public String describe() { ... } // can be overridden
}
Final classes β can't be subclassed
public final class String { ... } // JDK β designed to be immutable
public final class Money { ... } // value type β no subclasses allowed
Effectively final β for lambdas and inner classes
String prefix = "hello ";
list.forEach(s -> System.out.println(prefix + s)); // β
prefix never reassigned
String prefix = "hello ";
prefix = "hi "; // β now referenced in lambda below:
list.forEach(s -> System.out.println(prefix + s)); // compile error
A variable captured by a lambda or inner class must be effectively final β unchanged after initialisation, even without the keyword.
Records and final
Records are implicitly final and their components are implicitly final fields. You can't make them non-final.
Common mistakes
- Confusing
finalwith immutable βfinal List<X>doesn't preventlist.add(...). UseList.copyOffor an immutable list. - Not using
finalon fields β every field that doesn't need to change should befinal. Make immutability the default. - Using
finalon method parameters reflexively β opinions vary; it reduces accidental reassignment but adds noise. Some teams enable it by convention.
Related
Pillar: Java keywords. See also final variables, records, static.