Immutable object

An immutable object is one whose state cannot change after construction. Java has several famous immutables: String, all wrapper classes (Integer, Long…), java.time types (LocalDate, Instant…), and all records (when components are immutable).

Building an immutable class

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 long cents()        { return cents; }
    public String currency()   { return currency; }

    public Money plus(Money other) {
        if (!currency.equals(other.currency)) throw new IllegalArgumentException();
        return new Money(cents + other.cents, currency);  // returns a NEW object
    }
}

Immutability checklist

  1. Mark the class final (so it cannot be subclassed and mutated).
  2. All fields are private final.
  3. No setters. No methods that modify state.
  4. If a field is a mutable type (Date, List), make defensive copies in the constructor and in accessors, or use immutable equivalents (Instant, List.copyOf()).

Why immutability matters

  • Thread-safe by construction β€” no synchronization needed to share across threads.
  • Safe as map keys and set elements β€” hashCode cannot change.
  • Easier to reason about β€” no state changes to track through the code.
  • Free caching β€” two identical immutable objects are interchangeable.

Records make it easy

public record Money(long cents, String currency) {}
// Immutable for free β€” components are final, no setters possible.