Arrays.asList method returns not java.util.ArrayList

Arrays.asList and java.util.ArrayList are not compatible

A static method that can create a List object from variadic arguments, ʻArrays.asList (T ... t) , but does not return an object of `java.util.ArrayList`` because they have similar names. ..

Code like the following will result in a compilation error.

java.util.ArrayList<Integer> arrayList = Arrays.asList(1,2,3); // no instance(s) of type variable(s) T exist so that List<T> conforms to ArrayList<Integer>

Since it is returned as a List type, it looks good if you cast it to java.util.ArrayList, and the compile error actually disappears.

* A bad cast
java.util.ArrayList<Integer> arrayList = (java.util.ArrayList<Integer>) Arrays.asList(1,2,3);

But at runtime I get a ClassCastException. Never do it.

Take a look at the contents of Arrays.asList

Take a peek at the implementation to see what the `ʻArrays.asList`` method is returning.

Array.java


@SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
...Abbreviation

You are returning an ArrayList with return new ArrayList <> (a);! I want to say that, but let's follow the `ʻArrayList`` further.

Array.java


/**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
...Abbreviation

You can see that it has a nested private and static ArrayList class in the Array class, and it is new and instantiated.

And that ArrayList class inherits from ʻAbstractList``, not the `java.util.ArayList`` class. (Since java.util.ArayList also inherits AbstractList, the inheritance hierarchy is the same)

__ In other words, you can see that Arrays.asList returns an instance of the same name as java.util.ArrayList (excluding packages) but a different class (no inheritance relationship). __

__ The java.util.ArrayList class and the ArrayList class`` in the `ʻArrays class are not compatible. __

Therefore the above

* A bad cast
java.util.ArrayList<Integer> arrayList = (java.util.ArrayList<Integer>) Arrays.asList(1,2,3);

Found out why it throws a ClassCastException.

Read the official documentation

If you read [Official documentation of Arrays class] link-Arrays, the explanation of asList is

Returns a fixed size list that works with the specified array.

a.

In other words, the __ArrayList class in the Arrays class is a fixed-length list , which is different from the __ variable-length list java.util.ArrayList.

Do not add to the List obtained by Arrays.asList

As confirmed above, the ArrayList class in Arrays has a fixed length, so the number of elements in the __list cannot be changed. __

So the following code will compile, but the exception `ʻUnsupportedOperationException`` will occur at runtime.

//I'm trying to add an element to a fixed length list
List<Integer> list1 = Arrays.asList(1,2,3);
list1.add(4);  // UnsupportedOperationException

This is in the description of the add method of the inherited [Official documentation of the AbstractList class] link-AbstractList.

This implementation throws an UnsupportedOperationException unless add (int, E) is overridden.

This is because the ArrayList class in Arrays does not override the ʻadd (int, E) method.

Many people would use add if they didn't know that Arrays.asList would return a fixed-length list.

How about remove

By the way, if you also use the remove method, `ʻUnsupportedOperationException`` will occur at runtime.

It's a fixed-length list, so I feel a strong will to never change the size.

Summary

The list returned by `ʻArrays.asListis not compatible with java.util.ArrayList``. Don't cast.

Incidentally, the list returned by `ʻArrays.asList`` is a fixed-length list. If you change the size later, an exception will occur.

If you really want to use it with java.util.ArrayList type, pass it to the argument of the constructor and use it. Since it is no longer a fixed length, you can add and remove it.


//No compile error or ClassCastException at run time
List<Integer> list1 = Arrays.asList(1,2,3);
ArrayList<Integer> list2 = new ArrayList<>(list1);

However, since __Arrays.asList returns completely eliminates the merit of fixed-length list __, I think that it is not necessary to write such code, and it is better to handle the list with the List interface type. I think it's the best.

Recommended Posts

Arrays.asList method returns not java.util.ArrayList
[Ruby] Method that returns truth