Arrays.aslist() and UnsupportedOperationException

UnsupportedOperationException is a member of Java Collection Framework, it’s thrown when an operation cannot be performed because it is not supported for that particular collection.

One of the most common causes for this exception is using the Arrays.asList() method, Let’s dive into the source codes and figure out why this could happen.

Exception Example

    List<Integer> list1 = Arrays.asList(1,2,3,4,5);
    list1.set(0, 10); // ok, override the first value of list1 with 10
    list1.remove(0); // throw UnsupportedOperationException
    list1.add(6); // throw UnsupportedOperationException

As the codes shown above, the list element value can be edited, but adding new element to the list, or removing elements from list are not allowed.

Secret in the Source Code

From the source code of Arrays.asList(), we know that it simply returns an ArrayList, it is strange that neither add() nor remve() operation are not allowed.

    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

If we check it carefully, we will find that the ArrayList here is different from java.util.ArrayList we normally used. The ArrayList returned by Array.asList() is of type java.util.Arrays.ArrayList, it is an inner class of java.util.Arrays.

   private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable
    {
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
        // other fields and methods
    }

java.util.Arrays.ArrayList is actually a fixed size array, The reasons for this judgement are:

  • First, it uses a generic array to hold the elements, not a java collection such as List or Set.
  • Second, there is no machanism to change the length of internal array, unlike what’s in java.util.ArrayList.

The length of array cannot be changed, this is the design intention of Arrays.asList() why we get UnsupportedOperationException while calling add or remove methods. But where is the exception being thrown?

In the declaration of java.util.AbstractList, which is the parent class of java.util.Arrays.ArrayList , both add and remove method thrown UnsupportedOperationException directly, this is where the exception being thrown.

    public boolean add(E e) {
        add(size(), e);
        return true;
    }
    public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
    public E remove(int index) {
        throw new UnsupportedOperationException();
    }

How to Resolve UnsupportedOperationException

The List returned by the Arrays.asList() method can be passed to a new java.util.ArrayList object, which can be modified:

    List<Integer> list1 = Arrays.asList(1,2,3,4,5);
    List<Integer> list2 = new ArrayList<>(list1);
    // or one line
    List<Integer> list = new ArrayList<>(Arrays.asList(1,2,3,4,5));

Here, a new java.util.ArrayList object with list returned from the Arrays.asList() method. When a new element is added to or removed from the ArrayList, it works as expected and the UnsupportedOperationException will never be thrown.

Conclusion

From this article, we know that Arrays.asList() returns a fixed-size list, which is actually backed by a specified array. There is no machinasm to change the length of this array, so add or remove operation are not allowed.