The 30 second answer
List.of, from Java 9, gives a truly unmodifiable list: add, set and remove all throw, and it rejects null elements. Arrays.asList gives a fixed-size view over an array: I can't add or remove, but I can set an element, and that change writes through to the original array. Arrays.asList also allows nulls. So List.of is safer for constants and return values.
List.of(...) | Arrays.asList(...) | |
|---|---|---|
| add / remove | throws UnsupportedOperationException | throws UnsupportedOperationException |
| set | throws | allowed, writes through to the array |
| null elements | NullPointerException | allowed |
| backed by array | no | yes (a view) |
contains(null) | throws NullPointerException | works |
String[] arr = {"a", "b"};
List<String> view = Arrays.asList(arr);
view.set(0, "z"); // arr[0] is now "z"
List.of("a", "b").set(0, "z"); // UnsupportedOperationExceptionRelated: List.copyOf (Java 10) makes an unmodifiable copy of any collection, and Stream.toList() (Java 16) returns an unmodifiable list. Collections.unmodifiableList is only a read-only view; changes to the underlying list are still visible through it.
Sources: List Javadoc: Unmodifiable Lists, Arrays.asList Javadoc), JEP 269: Convenience Factory Methods for Collections
Sources (0)
See inline citations in the answer above.