Collections: an unmodifiable wrapper does not deep-freeze

Collections.unmodifiableList stops changes to the list, but the elements inside stay mutable - immutability has to be designed in, not bolted on.

Code
class Box { int value; Box(int v) { value = v; } public String toString() { return "Box(" + value + ")"; } }

var boxes = new ArrayList<>(List.of(new Box(1), new Box(2)));
List<Box> readOnly = Collections.unmodifiableList(boxes);

readOnly.get(0).value = 99;                 // the element itself is still mutable
System.out.println("element mutated through the view: " + readOnly);

try {
    readOnly.add(new Box(3));
} catch (UnsupportedOperationException e) {
    System.out.println("but the list itself cannot be structurally changed");
}
Output
element mutated through the view: [Box(99), Box(2)]
but the list itself cannot be structurally changed
Advertisement

Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.

Published 2026-07-30