Почему попытка изменить неизменяемую (unmodifiable) коллекцию в Java вызывает исключение?

«Почему попытка изменить неизменяемую (unmodifiable) коллекцию в Java вызывает исключение?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Попытка модификации неизменяемой коллекции вызывает UnsupportedOperationException из-за принципа защиты от случайных изменений (defensive programming). Эти коллекции являются обертками, которые явно запрещают операции изменения.

Как создаются неизменяемые коллекции:

List<String> mutableList = new ArrayList<>(Arrays.asList("A", "B", "C"));
List<String> unmodifiableList = Collections.unmodifiableList(mutableList);

unmodifiableList.add("D"); // Выбросит UnsupportedOperationException
unmodifiableList.remove(0); // Выбросит UnsupportedOperationException

Причины и преимущества такого поведения:

  1. Безопасность данных: Гарантирует, что коллекция, переданная в другой часть программы или возвращенная из метода, не будет неожиданно изменена. Это критически важно для многопоточности и API.
  2. Явность контракта: Метод, возвращающий Collections.unmodifiableList(...), четко сообщает клиенту: "Вы можете только читать эти данные".
  3. Производительность: Неизменяемые коллекции могут использовать оптимизации, так как их внутреннее состояние постоянно.

Важное замечание: Коллекция, возвращаемая Collections.unmodifiableList(), является view (представлением) исходной коллекции. Если изменить исходную коллекцию, это изменение будет видно через неизменяемую обертку.

mutableList.add("D"); // Это сработает
System.out.println(unmodifiableList); // Выведет [A, B, C, D]

Для создания полностью независимой и неизменяемой копии используйте List.copyOf() (Java 10+) или методы of() (Java 9+).