An immutable object never changes after construction, so it can be shared across threads with zero locking. This single property eliminates a whole category of bugs.
Build immutability in
Make fields final, do not expose setters, and defensively copy any mutable
inputs so callers cannot reach in and change your state.
public final class Money {
private final long cents;
private final String currency;
public Money(long cents, String currency) {
this.cents = cents;
this.currency = Objects.requireNonNull(currency);
}
public Money plus(Money other) {
return new Money(this.cents + other.cents, currency);
}
}Records make it trivial
For pure data carriers, a record generates the constructor, accessors, and
equals for you — all immutable by default.
public record Point(int x, int y) {}Takeaways
- Return new instances from "mutating" methods instead of changing state.
- Defensively copy mutable collections on the way in and out.
- Immutable objects are inherently thread-safe and cache-friendly.
Wrap exposed collections with List.copyOf so callers receive an unmodifiable
view they cannot alter.