Collections.unmodifiableList() не даёт иммутабельность — это view

Метод оборачивает список в неизменяемую обёртку: вызов add() или remove() на результате бросает UnsupportedOperationException. Кандидаты часто останавливаются на этом и называют список полностью иммутабельным.

На деле unmodifiableList() — это view над тем же backing-массивом. Обёртка запрещает мутацию только через себя. Если где-то в коде осталась прямая ссылка на исходный List, содержимое поменяется и в обёртке — это один и тот же объект в памяти.

List source = new ArrayList<>( List.of("a", "b") );

List view = Collections .unmodifiableList(source);

source.add("c");

System.out.println(view.size()); // 3, а не 2

Настоящая иммутабельность — List.of() или List.copyOf(): они копируют данные при создании, а не оборачивают чужую ссылку.

Следом спросят: а List.copyOf() всегда копирует? Нет — если аргумент уже неизменяемый список, созданный тем же API, copyOf() может вернуть его же без копии, потому что мутировать его и так нельзя.

unmodifiableList() защищает от чужого API, а не от кода, у которого есть исходная ссылка на список.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки