List.of()
Creates a compact, unmodifiable list in one expression, and rejects nulls so bad data fails early.
static <E> List<E> of(E... elements)- Added in Java Java 9
Parameters
| Parameter | Type | Description |
|---|---|---|
$elements | E... | The elements to store. There are fixed-arity overloads for zero to ten elements and a varargs overload for more; none of them may be null. |
Return value
List<E>An unmodifiable list holding the given elements in the order they were passed.
Errors
NullPointerException if any element is null, or if the array passed to the varargs overload is null. The returned list throws UnsupportedOperationException from add, set, remove, clear, sort and every other mutator.
List.of builds a list from the values you pass and hands back a list that cannot be changed. It is the shortest way to write a fixed list in Java: default roles, allowed HTTP methods, the columns of a report, test fixtures.
There are overloads for zero to ten arguments plus a varargs version, so small lists do not allocate an extra array. The elements keep the order you wrote them in, and the list implements equals by content, so List.of("a", "b") equals an ArrayList holding the same two strings.
Unmodifiable, not just read-only by convention
Every mutating method throws UnsupportedOperationException: add, set, remove, clear, sort, replaceAll, removeIf. That is the point. A service can return List.of(...) and know no caller can quietly change shared state. When you do need to edit, copy it: new ArrayList<>(List.of(...)).
The list is shallowly immutable. If the elements are mutable objects, their fields can still change. Records and strings avoid that problem.
Nulls are rejected
List.of throws NullPointerException if any element is null. The surprise is that queries throw too: contains(null) and indexOf(null) on a List.of list throw instead of returning false or -1. Guard values that come from request parameters or database columns before you look them up.
Related factories
List.copyOf(collection)(Java 10) makes an unmodifiable copy of an existing collection. Use it in record constructors and when returning internal state.Stream.toList()(Java 16) also returns an unmodifiable list, but it allows null elements.Arrays.asList(array)is different: it is a fixed-size view over the array, it allowssetand nulls, and changes to the array show through.
Do not rely on identity or synchronise on these lists. They are value-based, and the JDK is free to reuse instances, for example for the empty list.
Example
When to use it
- Declaring the fixed set of roles, scopes or HTTP methods an endpoint accepts as a constant.
- Returning a small result from a service method so callers cannot modify shared state.
- Building request bodies and expected values in tests without several add calls.
Frequently asked questions
Why does List.of throw UnsupportedOperationException when I call add?
List.of returns an unmodifiable list by design. Copy it into a mutable list first with new ArrayList<>(List.of(...)) if you need to add, remove or sort elements.
What is the difference between List.of and Arrays.asList?
Arrays.asList is a fixed-size view over an array: set works, add and remove do not, nulls are allowed and changes to the array show through. List.of copies the values, rejects nulls and allows no changes at all.
Can List.of contain null?
No. Creating one with a null element throws NullPointerException, and so do contains(null) and indexOf(null). Use an ArrayList or Stream.toList() if you really need null elements.
More examples
List.of copies, Arrays.asList wraps
Passing an array to List.of copies its elements, so later changes to the array do not leak in. Arrays.asList is a live view of the same array in both directions.
void main() {
String[] codes = {"GB", "FR", "DE"};
List<String> view = Arrays.asList(codes);
List<String> copy = List.of(codes);
codes[0] = "IE";
IO.println("asList sees change: " + view);
IO.println("List.of is a copy: " + copy);
view.set(1, "ES");
IO.println("array after set: " + Arrays.toString(codes));
try {
copy.set(1, "ES");
} catch (UnsupportedOperationException e) {
IO.println("List.of rejects set");
}
}
// Output:
// asList sees change: [IE, FR, DE]
// List.of is a copy: [GB, FR, DE]
// array after set: [IE, ES, DE]
// List.of rejects setLooking up a value that might be null
Lists from List.of refuse null even in queries. A null check in front of the lookup turns the crash into an ordinary false.
void main() {
List<String> allowed = List.of("GET", "POST");
String method = null; // e.g. a missing request field
try {
IO.println(allowed.contains(method));
} catch (NullPointerException e) {
IO.println("contains(null) threw NullPointerException");
}
IO.println(method != null && allowed.contains(method));
}
// Output:
// contains(null) threw NullPointerException
// falseDefensive copy in a record
List.copyOf in the compact constructor detaches the record from the caller's mutable list. The record's accessor then returns a list nobody can modify.
record Order(String id, List<String> items) {
Order {
items = List.copyOf(items);
}
}
void main() {
List<String> basket = new ArrayList<>(List.of("book", "pen"));
Order order = new Order("A-1", basket);
basket.add("lamp");
IO.println(order.items());
try {
order.items().clear();
} catch (UnsupportedOperationException e) {
IO.println("items cannot be changed");
}
}
// Output:
// [book, pen]
// items cannot be changed
Discussion