How do you make a class truly immutable in Java?
Options
- Mark only the class as
final; nothing more is needed finalclass, private final fields, no setters, copies (Correct option)- Add
volatileto every one of the fields in the class - Make every field
staticso that all objects share it
Answer
Make the class final, all fields private final, no setters, and defensively copy any mutable object that comes in or goes out
Why
An immutable object never changes after construction, so it is automatically thread-safe and can be shared and cached freely (String and LocalDate are immutable).
Recipe: (1) final class so nobody subclasses and adds mutability, (2) private final fields, (3) no setters, (4) if a field is a mutable object (a List, a Date), copy it in the constructor and return a copy or an unmodifiable view in the getter.
A final List field alone is not enough: the list contents could still change. Records do most of this for you (but still need defensive copies of mutable components).
public final class Team {
private final List<String> members;
public Team(List<String> m) { this.members = List.copyOf(m); }
public List<String> members() { return members; } // already unmodifiable
}Remember
final fields + no setters + defensive copies.