Bozho's approved answer is correct. Here is a bit more information, sample code, and suggested alternative.
Unmodified list maintained by source list
This unmodifiableList method in the Collections class does not create a new list; it creates a pseudo-list supported by the original list. Any additions or deletions of attempts made using the "non-editable" object will be blocked, so the name matches its purpose. But really, as you have shown, the original list can be changed and at the same time affect our secondary not entirely unmodifiable list.
This is stated in the class documentation:
Returns an unmodifiable representation of the specified list. This method allows modules to provide users with access to internal read-only lists. Query operations on the returned “read” list to the specified list and attempts to modify the returned list, whether direct or through its iterator, throw an UnsupportedOperationException.
This fourth word is the key: view . The new list object is not a new list. This is an overlay. Just as tracing paper or transparent film above the pattern stops you from creating marks on the drawing, this does not prevent you from switching to changing the original drawing.
The moral of the story: do not use Collections.unmodifiableList to create protected copies of lists.
Ditto for Collections.unmodifiableMap , Collections.unmodifiableSet etc.
Here is another example demonstrating the problem.
String dog = "dog"; String cat = "cat"; String bird = "bird"; List< String > originalList = new ArrayList<>( 3 ); originalList.add( dog ); originalList.add( cat ); originalList.add( bird ); List< String > unmodList = Collections.unmodifiableList( originalList ); System.out.println( "unmod before: " + unmodList );
Google guava
Instead of the Collections class for defensive programming, I recommend using the Google Guava library and its ImmutableCollections .
You can create a fresh list.
public static final ImmutableList<String> ANIMALS = ImmutableList.of( dog, cat, bird );
Or you can create a protective copy of an existing list. In this case, you will receive a new separate list. Removing from the source list will not affect (compress) the immutable list.
ImmutableList<String> ANIMALS = ImmutableList.copyOf( originalList );
But remember that while the collection’s own definition is separate, the contained objects are shared by both the original list and the new immutable list. When creating this protective copy, we do not duplicate the dog object. Only one dog object remains in memory, both lists contain a link pointing to the same dog. If the properties in the dog object are changed, both collections point to the same object in the same dog, so both collections will see the value of the new dog value.