Why can’t the Lists created by Arrays.asList() and Collections.singletonList() add elements?
UnsupportedOperationException
List collections created by Arrays.asList() and Collections.singletonList() cannot call their add method (ImmutableList) or an UnsupportedOperationException will be reported.
Arrays.asList()
List<Integer> list = Arrays.asList(1, 2, 3);
list.add(4);
Collections.singletonList()
List<Integer> list = Collections.singletonList(1);
list.add(2);
Throw an exception:
Reason
As you can see from the exception stack above, both are calling the AbstractList.add() method, which causes an exception.
Let’s take a look at the implementation of Arrays and Collections:
Arrays
Implementation of asList(T..a):
@SafeVarargs
@SuppressWarnings("varargs")
public static <T> List<T> asList(T… a) {
return new ArrayList<>(a);
}
An ArrayList object is constructed, but here ArrayList belongs to the inner class of Arrays, not java.util.ArrayList.
Since Arrays#ArrayList does not implement the add(E e) method, it can only call the add method of its parent class AbstractList.
Let’s look at Collections
Collections
Implementation of singletonList(T o):
public static <T> List<T> singletonList(T o) {
return new SingletonList<>(o);
}
A SingletonList object is constructed, which also does not implement the add(E e) method, and needs to call the `add` method of the parent class AbstractList.
As you can see from the previous UnsupportedOperationException, which was thrown from the AbstractList.add(E e) method, let’s take a look at the implementation of this parent method:
AbstractList.add(E e)
public boolean add(E e) {
add(size(), e);
return true;
}
add(int index, E element):
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
As you can see here the exception is thrown directly and needs to be reimplemented by subclass inheritance
How to fix it
Before the add, use `new ArrayList` to reconstruct a new List.
List<Integer> list = Collections.singletonList(1);
list = new ArrayList<>(list);
list.add(2);