Arrays.asList生成的List不能使用add和remove方法的原因

2,045 阅读1分钟

前因

在实际开发中我使用Arrays.asList 将一个字符串数组转化为List使用,后续需要根据规则判断从该List中移除元素 但是移除的时候出现了错误java.lang.UnsupportedOperationException

String[] strs = {"小A","小B","小C"};
List<String> stringList = Arrays.asList(strs);
stringList.remove("小A");

错误:throw java.lang.UnsupportedOperationException

探索

  • 查询Arrays.asList的定义
/**

 * Returns a fixed-size list backed by the specified array.  (Changes to

 * the returned list "write through" to the array.)  This method acts

 * as bridge between array-based and collection-based APIs, in

 * combination with {@link Collection#toArray}.  The returned list is

 * serializable and implements {@link RandomAccess}.

 *

 * <p>This method also provides a convenient way to create a fixed-size

 * list initialized to contain several elements:

 * <pre>

 *     List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

 * </pre>

 *

 * @param <T> the class of the objects in the array

 * @param a the array by which the list will be backed

 * @return a list view of the specified array

 */

@SafeVarargs

@SuppressWarnings("varargs")

public static <T> List<T> asList(T... a) {

    return new ArrayList<>(a);

}

翻译:返回了一个定长的List,这个方法用于转化array系列API与collection系列API,返回值仅仅是数组简单包装而成的List而已,并不能直接修改其长度。

Think In java的解释

It’s also possible to use the output of Arrays.asList( ) directly, as a List, but the

underlying representation in this case is the array, which cannot be resized. If you try to 

add( ) or delete( ) elements in such a list, that would attempt to change the size of an array, 

so you’ll get an "Unsupported Operation" error at run time.

注意: 这里返回的是new ArrayList,我们平时定义的List list = new ArrayList();为何平时定义的ArrayList可以add和remove这里不可以呢? 是因为这里的new ArrayList其实是Arrays内部自己实现的一个内部类

 private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable

也就是说

  • Arrays.asList返回的ArrayList 实际上是Arrays的内部类 属于java.util.Arrays$ArrayList
  • List list = new ArrayList 属于java.util.ArraysList 查询ArrayList源码后发现他并没有实现add和remove方法,因此再向上一层查看AbstractList的源码
public void add(int index, E element) {
        throw new UnsupportedOperationException();
    }
public E remove(int index) {
    throw new UnsupportedOperationException();
}

因此抛出了java.lang.UnsupportedOperationException

至此就了解了为什么Arrays.asList()转化后的List无法add和remove

解决办法

使用new ArrayList<>(Arrays.asList())

示例:List list = new ArrayList<>(Arrays.asList(1,2,3));

总结

1.Arrays.asList返回的是一个定长数组不能add和remove(结论),add和remove会返回java.lang.UnsupportedOperationException

2.Arrays.asList返回的ArrayList 不是真的ArrayList 而是AbstractList中的一个内部类 AbstractList的add和remove方法throw java.lang.UnsupportedOperationException(原因),真正的ArrayList继承了AbstractList,并实现了add和remove方法

3.解决方法:使用new ArrayList<>(Arrays.asList())

示例:List list = new ArrayList<>(Arrays.asList(1,2,3));