Codectionary / Developer documentation / Java

Unmodifiable Snapshots with List.copyOf

Take a stable list snapshot while understanding shallow copying and null restrictions.

What it is and why to use it

Returning an internal mutable list lets a caller change your state. List.copyOf creates an unmodifiable list containing the source elements in iteration order. Later additions and removals in the source do not appear in the returned list. The method is available from Java 10.

How it works

The snapshot holds the element references, not deep copies of each object. It rejects null elements and a null source. If the source is already a suitable unmodifiable list, an implementation can reuse it, so object identity is not part of the contract.

Common mistakes and limitations

Unmodifiable does not mean deeply immutable: if an element is mutable, changes inside that object remain visible through its reference. Use immutable element types or deliberate defensive copies when deeper isolation is required.

Try it and keep learning

Save the complete example below as Main.java. With a JDK supporting Java 17, compile using javac --release 17 Main.java, then run java Main from the same directory. These examples need only the standard library and fixed input; they do not require packages, files or network access.

Syntax

List<String> snapshot = List.copyOf(source);

Examples

Unmodifiable Snapshots with List.copyOf

Complete Main.java example — Java 17 or later, without preview features.

import java.util.ArrayList;
import java.util.List;

public class Main {
  public static void main(String[] args) {
    List<String> source = new ArrayList<>(List.of("Read"));
    List<String> snapshot = List.copyOf(source);
    source.add("Practice");
    System.out.println(source);
    System.out.println(snapshot);
  }
}
  1. source starts as a mutable list with one element.
  2. copyOf captures that list’s current contents. Adding Practice changes source only.
  3. The two prints show the difference between current state and a snapshot. Calling snapshot.add would throw UnsupportedOperationException rather than change either list.
  4. Expected output: [Read, Practice] [Read]

Best practices

  • Use snapshots for results that should not track future source changes.
  • Document whether elements themselves can change.

Runtime & versions

Java Virtual Machine. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

Java Language Specification

Specifications & further reading