Core Javahigh

Immutability

An immutable object's state cannot change after construction. String, Integer, and other boxed types are immutable. Immutable objects are inherently thread-safe and can be freely shared.

Memory anchor

Immutable object = a message carved in stone. You can pass the stone tablet around to anyone safely -- nobody can secretly change the words. Mutable = a whiteboard anyone can erase.

Expected depth

To make a class immutable: declare it final (prevents subclassing), make all fields private final, initialize all fields in the constructor, do not provide setters, and perform defensive copies of mutable fields (arrays, collections) in the constructor and in getters. java.time types (LocalDate, etc.) are immutable. Collections.unmodifiableList() returns an unmodifiable view — the underlying list can still be mutated. List.of() (Java 9+) returns a truly immutable list.

Deep — senior internals

Immutability enables safe publication — because an immutable object's state is fixed at construction and fields are final, the Java Memory Model guarantees that any thread that sees the reference also sees the fully initialized state (final field freeze guarantee in JMM §17.5). This is the reason immutable objects don't need synchronized access. String's cached hash (a non-final field) is a carefully reasoned exception — the lazy initialization is safe because the result is deterministic. Value types (Project Valhalla) push immutability into the type system at a deeper level, enabling stack allocation of value objects.

🎤Interview-ready answer

Immutable classes must be final, have all private final fields, set all state in the constructor, and defensively copy any mutable inputs and outputs. The JMM's final field freeze guarantee means a thread that reads an object reference through any publication mechanism will see the fully initialized final fields without synchronization. This is why immutable objects are the safest currency for concurrent code — no locks, no races.

Common trap

Making a field final does not make a mutable object it points to immutable — final List<String> means the reference can't change, but the list contents can be freely modified.