Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Arrays.asList(array) gives you a fixed-size list view backed by an object array; List.of(...) gives you an unmodifiable list that does not track later changes to a source array and rejects null. Neither is a normal resizable list: use new ArrayList<>(...) when you need to add or remove elements.

Quick comparison

Behavior Arrays.asList(...) List.of(...)
Available since Java 8 and earlier Java 9
List size Fixed Fixed
set(index, value) Allowed; updates the backing array Throws UnsupportedOperationException
add or remove Throws UnsupportedOperationException Throws UnsupportedOperationException
Relationship to supplied object array Live, backed view No live backing relationship
null elements Allowed Rejected with NullPointerException
Typical use Use an existing array through the List interface Create a read-only list of known values

The key distinction is not simply “mutable versus immutable.” Arrays.asList lets you replace existing elements but not change the list’s size. List.of does not allow list mutation, including replacement with set.

How Arrays.asList works

For an object array, Arrays.asList returns a fixed-size list backed by that array:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
String[] colors = {"red", "green", "blue"};
List<String> colorsList = Arrays.asList(colors);

colors[0] = "yellow";
System.out.println(colorsList.get(0)); // yellow

colorsList.set(1, "purple");
System.out.println(colors[1]);         // purple

Because each list position corresponds to an array element, set is supported. Operations that would change the number of elements are not:

colorsList.add("black"); // UnsupportedOperationException
colorsList.remove("red"); // UnsupportedOperationException

That makes Arrays.asList useful when an API requires a List but you want to work with an existing object array. It is not an independent copy: mutations through either the array reference or the list’s set method are visible through the other. The Arrays API describes the result as a fixed-size list backed by the specified array.

How List.of works

Use List.of to create an unmodifiable list from values, on Java 9 or later:

List<String> colors = List.of("red", "green", "blue");

Calls to set, add, and remove throw UnsupportedOperationException. If you pass an object array, the list does not remain connected to it:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
String[] source = {"red", "green", "blue"};
List<String> colors = List.of(source);

source[0] = "yellow";
System.out.println(colors.get(0)); // red

List.of also rejects nulls. A null element or a null varargs array causes NullPointerException during construction:

List<String> values = List.of("A", null); // NullPointerException

This can be helpful when null is invalid data: the factory surfaces it immediately rather than allowing it into the list. For the exact contract and supported Java versions, see the Java List API.

Unmodifiable does not mean deeply immutable

List.of prevents changes to the list’s structure and element references. It does not freeze objects stored in the list. For example, a contained StringBuilder can still be changed:

List<StringBuilder> list = List.of(new StringBuilder("A"));
list.get(0).append("B");
System.out.println(list.get(0)); // AB

Passing an array to List.of

A reference array passed to List.of is normally interpreted as the varargs elements. Thus this produces a list containing three strings:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
String[] words = {"one", "two", "three"};
List<String> wordsList = List.of(words);

If you want one list element whose value is the array itself, state that element type explicitly:

List<String[]> oneElement = List.<String[]>of(words);

This overload distinction is easy to miss when moving array-handling code between APIs. The List API documentation describes the varargs behavior.

Watch out for primitive arrays

Arrays.asList accepts reference-type varargs. A primitive array such as int[] is itself an object, so it becomes one list element—not a list of boxed integers:

int[] numbers = {1, 2, 3};
List<int[]> oneElement = Arrays.asList(numbers);

System.out.println(oneElement.size());     // 1
System.out.println(oneElement.get(0)[1]); // 2

For a List<Integer>, box the values. On Java 16 or later, Stream.toList() provides an unmodifiable result:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
List<Integer> values = Arrays.stream(numbers)
        .boxed()
        .toList();

If you need a mutable list, collect into an ArrayList instead:

List<Integer> mutable = Arrays.stream(numbers)
        .boxed()
        .collect(Collectors.toCollection(ArrayList::new));

By contrast, Integer[] is an object array, so Arrays.asList(integerArray) produces a list of its integer elements.

Which should you choose?

Need Use
A list view over an existing object array, with changes to existing elements shared Arrays.asList(array)
A list of known values that callers must not change List.of(...) (Java 9+)
A resizable, independently mutable list new ArrayList<>(...)
An unmodifiable wrapper compatible with Java 8 Collections.unmodifiableList(...)
An unmodifiable snapshot of a collection List.copyOf(collection) (Java 10+)

For a mutable list from an object array:

String[] array = {"A", "B", "C"};
List<String> mutable = new ArrayList<>(Arrays.asList(array));
mutable.add("D");

For a mutable list from literals on Java 9 or later:

List<String> mutable = new ArrayList<>(List.of("A", "B", "C"));

For an unmodifiable list on Java 8:

List<String> readOnly =
        Collections.unmodifiableList(Arrays.asList("A", "B", "C"));

Oracle’s Core Libraries guide shows List.of for Java 9 and later and the Collections.unmodifiableList pattern for Java 8.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

View versus snapshot: the unmodifiable wrapper difference

Collections.unmodifiableList blocks mutation through the returned wrapper, but it does not copy the underlying list. Changes made through another reference are still visible:

List<String> source = new ArrayList<>(List.of("A", "B"));
List<String> view = Collections.unmodifiableList(source);

source.set(0, "X");
System.out.println(view.get(0)); // X

If you want an unmodifiable snapshot of an existing collection, use List.copyOf on Java 10 or later:

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

List.copyOf rejects null elements. For Java 8, make a copy first and then wrap it if you need a snapshot:

List<String> snapshot = Collections.unmodifiableList(
        new ArrayList<>(source));

Common failure modes

  • Adding to an Arrays.asList result: it has a fixed size, so add and remove throw UnsupportedOperationException. Copy into an ArrayList if the list must grow.
  • Calling set on a List.of result: it is unmodifiable, so replacement also throws. Use a mutable list if elements need to change.
  • Calling Arrays.asList immutable: it is not immutable; set and the backing array can change its elements.
  • Assuming int[] becomes List<Integer>: it becomes one element of type int[]. Box the stream or loop over the values.
  • Assuming List.of(array) always means one array element: reference-array contents are normally expanded as varargs. Use List.<String[]>of(array) for one array element.
  • Using List.of on Java 8: it is not part of the Java 8 API. Use an appropriate Java 8 alternative.
  • Assuming an unmodifiable wrapper is a snapshot: it reflects changes made through the wrapped collection. Copy first if you need independent contents.

Performance and implementation details

Do not choose between these factories based on a blanket claim that one is always faster. Arrays.asList is a view backed by the array; List.of has different unmodifiable semantics and does not expose that live relationship. Allocation and performance can vary with JDK release, list size, and workload. If performance is material, benchmark the exact application and runtime.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Both APIs promise behavior, not a concrete implementation class for application code to depend on. Avoid checks against internal class names or relying on object identity. The Java List API also describes the lists from List.of as value-based; do not use them as synchronization locks. The OpenJDK issue discussion provides historical context for why these factory methods are not interchangeable, but implementation-specific details can change.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.