All topics
library
intermediate

Immutability in Java

Design immutable classes correctly and understand their benefits for thread safety and defensive programming.

An immutable object cannot be modified after creation. Its state is set in the constructor and never changes.

Immutable object = a printed book. Once published, its content can't change. Everyone reads the same thing. Mutable object = a wiki page. Anyone can edit it while you're reading, and you might see inconsistent state.

Key Concepts

1
Rules for immutability: 1. Make the class final (or all methods final) — prevent subclass from adding mutable behavior 2. Make all fields private and final 3. Don't provide setters 4. If fields reference mutable objects (Date, List, Map), make defensive copies in constructor AND in getters 5. Perform all initialization in the constructor
2
Benefits: - Thread safety: immutable objects can be shared between threads without synchronization - Cache-friendly: safe to cache (value won't change under you) - Hash key safety: can be used as Map keys (hashCode never changes) - Simpler reasoning: no temporal coupling (object means the same thing everywhere)
3
JDK immutable examples: String, Integer (all wrappers), LocalDate, BigDecimal.
4
Java Records (Java 16): records are a concise syntax for immutable data carriers. record Point(int x, int y) {} generates private final fields, constructor, getters, equals, hashCode, toString. Records are not fully immutable if fields hold mutable references.
5
Defensive copying: when receiving mutable objects (List, Date), copy them in the constructor: this.items = List.copyOf(items). In getters, return unmodifiable views: Collections.unmodifiableList(items).