asList 引发的血案

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/PZHU_CG_CSDN/article/details/81629357

详情见如下代码:


  @Test
  public void testArraysList(){
      Integer[] a = {1,2,3,4,5};
      List<Integer> list = Arrays.asList(a);

      //尝试着向集合中再添加一个元素。
      list.add(6);

      for( Integer temp : list ) {
          System.out.println(temp);
      }
  }

  很简单的程序啊,不过,这段程序执行会不会有什么问题呢?

  运行后,会出现如下结果:


java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)

  UnsupportedOperationException,不支持的操作。居然不支持 List 的 add 方法,真是奇怪了!还是追根寻源,看看 asList 的源码:


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

  直接 new 了一个 ArrayList ,难道 ArrayList 不支持 add 方法?不可能呀!问题就出在这个 ArrayList 上,此处的 ArrayList 并非我们熟悉的 java.util.ArrayList,而是 ArrayList 工具类中的一个内置类。

这里写图片描述


    //这是一个私有的静态内部类
    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);
        }

        /*其他方法省略*/

    }

  这里的 ArrayList 是一个静态私有内部类,除了 Arrays 能访问外,其他类度不能访问。仔细看这个类,发现它没有提供 add 方法,那肯定是父类 AbstractList 提供的,来看代码:

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

  父类确实提了 add 方法,但是没有具体的实现,所以每个子类都要覆写 add 方法,而 ArrayList 没有覆写,因此 add 一个元素就会报错。

  
通过源码发现,ArrayList 静态内部类,它实现了如下一些常用方法: 

  • size:元素数量
  • toArray:转换为一个数组
  • get:获得指定元素
  • set:重置指定元素
  • indexOf:返回指定元素的索引下标
  • contains:是否包含某元素
  • sort:排序

      对于我们经常使用的 List.add 和 List.remove() 方法,都没有实现,也就是说, asList 返回的是一个长度不可变的列表,数组是多长,转换的列表也就是多长,不再保持列表动态边长的特性。
      

      虽然 Arrays.asList 用起便捷,但是却深藏着重大隐患 —— 列表长度无法修改切记千万不要把这样的 List 对象传递到一个允许 add 操作的方法中

猜你喜欢

转载自blog.csdn.net/PZHU_CG_CSDN/article/details/81629357