Немодифицируемый список поддерживается исходным списком
Этот метод unmodifiableList
в < служебный класс href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html">Collections
не создает новый список, он создает псевдо- список, поддерживаемый исходным списком. Любые попытки добавления или удаления, предпринятые через «неизменяемый» объект, будут заблокированы, поэтому имя соответствует своему назначению. Но на самом деле, как вы показали, исходный список может быть изменен и одновременно влияет на наш вторичный, не совсем неизменяемый список.
Это прописано в документации класса:
Возвращает неизменяемое представление указанного списка. Этот метод позволяет модулям предоставлять пользователям доступ «только для чтения» к внутренним спискам. Операции запроса в возвращаемом списке "прочитаны" до указанного списка, а попытки изменить возвращенный список, будь то напрямую или через его итератор, приводят к исключению UnsupportedOperationException.
Это четвертое слово является ключевым: view
. Новый объект списка не является новым списком. Это наложение. Так же, как калька или прозрачная пленка поверх рисунка не позволяет делать пометки на рисунке, но не мешает зайти под ним и изменить исходный рисунок.
Мораль истории: не используйте Collections.unmodifiableList для создания защитных копий списков.
То же самое для Collections.unmodifiableMap
, < a href="http://docs.oracle.com/javase/8/docs/api/java/util/Collections.html#unmodifiedSet-java.util.Set-">Collections.unmodifiableSet
и т. д.
Google Гуава
Вместо класса Collections
для защитного программирования я рекомендую использовать библиотеку Google Guava и ее ImmutableCollections.
Вы можете составить новый список.
public static final ImmutableList<String> ANIMALS = ImmutableList.of(
dog,
cat,
bird );
Или вы можете сделать защитную копию существующего списка. В этом случае вы получите свежий отдельный список. Удаление из исходного списка не повлияет (уменьшит) неизменяемый список.
ImmutableList<String> ANIMALS = ImmutableList.copyOf( originalList ); // defensive copy!
Но помните, хотя собственное определение коллекции является отдельным, содержащиеся в нем объекты являются общими как для исходного списка, так и для нового неизменяемого списка. Создавая эту защитную копию, мы не дублируем объект «собака». В памяти остается только один объект собака, оба списка содержат ссылку, указывающую на одну и ту же собаку. Если свойства в объекте «собака» изменены, обе коллекции указывают на один и тот же объект собаки, поэтому обе коллекции увидят новое значение свойства собаки.
person
Basil Bourque
schedule
02.09.2015
Collections.unmodifiableList
очень ясно, что неизменяемым является только возвращаемый список. Вы действительно ожидали, что этот вызов сделает исходный список неизменяемым? - person wero   schedule 03.09.2015