Detailed explanation
To make a Java collection unmodifiable, either expose a read-only view through Collections.unmodifiableList, Collections.unmodifiableSet, or Collections.unmodifiableMap, or create an unmodifiable collection using List.of, Set.of, or Map.of in Java 9 and later. These APIs prevent callers from changing the collection through the returned reference. For example, List<Integer> immutable = List.of(1, 2, 3); creates an unmodifiable list, and immutable.add(4) throws UnsupportedOperationException. This matters when returning internal data from a class: callers should not accidentally change state that the class owns.
The important distinction is between a view and an independent collection. Collections.unmodifiableList(original) wraps the supplied list rather than copying its elements. Reads are delegated to the backing list, while modification operations through the wrapper are blocked. If another reference changes original, those changes appear in the wrapper. To avoid this shared structural state, use Collections.unmodifiableList(new ArrayList<>(original)) for a defensive copy. Equivalent approaches apply to sets and maps. The wrapper also prevents modification through its iterators and relevant collection views, not just through obvious methods such as add or remove.
Factory methods such as List.of create collections whose contents cannot be structurally changed after creation; they do not expose a mutable backing collection. However, calling them 'truly immutable' needs qualification: they do not make their elements immutable. A List<Person> can still contain a Person whose name changes through a setter. Both approaches provide shallow protection, so deep immutability requires immutable elements or suitable defensive copies of mutable objects. Also, final only prevents reassigning a collection variable; it does not stop changes to the collection itself.
For an existing collection, Java 10 introduced List.copyOf, Set.copyOf, and Map.copyOf, which provide unmodifiable snapshots unaffected by later structural changes to the input. These methods may reuse an already suitable unmodifiable instance. The of and copyOf methods reject null elements, keys, or values as applicable; Set.of rejects duplicate elements, and Map.of rejects duplicate keys. Interviewers usually look for correct version awareness, the view-versus-snapshot distinction, and an explicit warning that unmodifiable collections do not guarantee deep immutability.
Key points to remember
- Collections.unmodifiableList/Set/Map returns an unmodifiable view that reflects backing-collection changes.
- List.of, Set.of, and Map.of create unmodifiable collections in Java 9+.
- List.copyOf, Set.copyOf, and Map.copyOf provide unmodifiable snapshots in Java 10+.
- Unmodifiable collections can still contain mutable objects; their protection is shallow.
- Mutation attempts such as List.of(1, 2, 3).add(4) throw UnsupportedOperationException.
Common mistakes candidates make
- Assuming an unmodifiable wrapper copies or freezes its backing collection.
- Claiming that final or an unmodifiable collection makes its elements immutable.
- Using Arrays.asList as an immutable list: it has a fixed size but still supports set.
Likely follow-up questions
How do you return an unmodifiable snapshot in Java 8?
Use Collections.unmodifiableList(new ArrayList<>(original)). The new list isolates later structural changes to original, but mutable element objects remain shared.
Can these collections contain null?
The of and copyOf methods reject null elements, keys, or values as applicable. Collections.unmodifiableList/Set/Map can expose nulls if the backing collection permits and contains them.
Is an unmodifiable collection automatically thread-safe?
No: an unmodifiable view can still have a backing collection that another thread modifies. An independent unmodifiable collection avoids structural mutations, but mutable elements and safe publication still need consideration.
Interview tip: Show List.of first, then contrast it with an unmodifiable wrapper and mention the mutable-element limitation.
