A list that rejects add calls may still change when another reference mutates its backing list. This small example shows why a read-only view and a copied list serve different purposes.
What you will build
See the difference between a snapshot and a read-only view by mutating the original list after creating both.
Before you start
JDK 11 or later. No additional libraries are needed.
1. Create ListSnapshots.java
import java.util.*;
public class ListSnapshots {
public static void main(String[] args) {
List<String> source = new ArrayList<>(Arrays.asList("Java"));
List<String> view = Collections.unmodifiableList(source);
List<String> snapshot = List.copyOf(source);
source.add("Python");
System.out.println("view=" + view);
System.out.println("snapshot=" + snapshot);
try {
snapshot.add("AI");
throw new AssertionError("Mutation unexpectedly succeeded");
} catch (UnsupportedOperationException expected) {
System.out.println("snapshot rejects add");
}
}
}
2. Run the example
javac ListSnapshots.java
java ListSnapshotsExpected result
The view prints [Java, Python], the snapshot prints [Java], and the final line confirms the snapshot rejects add.
How it works
Collections.unmodifiableList wraps the original list. A caller cannot change it through the wrapper, but changes made through the original reference remain visible.
List.copyOf produces an unmodifiable list containing the source elements at the time of the call. Later structural changes to the mutable source do not appear in that result.
Both approaches are shallow. If the list holds mutable objects, changing an object can still affect what you observe through either list. An immutable data model requires decisions about the elements as well as the collection.
copyOf rejects null elements. Check your data before adopting it in an existing code path. For configuration snapshots or return values you want to detach from a mutable source, this distinction is often more useful than simply asking whether add is allowed.
Test the edge cases
- Change the source before copying and compare the result.
- Try a null element and observe copyOf rejecting it.
- Replace strings with mutable objects to explore shallow copying.
Keep learning
Browse related tutorials. Reference: official documentation.
Reviewed 7 November 2026. AI-dependent examples require your own local model; generated text varies.