• 【List篇】使用Arrays.asList生成的List集合,操作add方法报错


    早上到公司,刚到工位,测试同事就跑来说"功能不行了,报服务器异常了,咋回事";我一脸蒙,早饭都顾不上吃,要来了测试账号复现了一下,然后仔细观察测试服务器日志,发现报了一个java.lang.UnsupportedOperationException异常
    在这里插入图片描述
    经排查发现,是将一个枚举类中两个元素,用Arrays.asList生成一个List集合,并且将这个集合当作一个方法的参数传递,在该方法中,正好使用此List进行了add方法的操作,导致异常发生了

    Arrays.asList

    使用此方式生成的List集合为什么不能执行add方法 ? 先来看下源码

     @SafeVarargs
     @SuppressWarnings("varargs")
     public static <T> List<T> asList(T... a) {
         return new ArrayList<>(a);  // ArrayList 是静态内部类
     }
     
    /**
      * @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;  //被final修饰,不可变
    
        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
    
        @Override
        public int size() {
            return a.length;
        }
    .......... 省略,可自行去看源码....
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    从源码可见,Arrays.asList 实际上也是new了一个 ArrayList,但是此处的ArrayList是Arrays这个类中的静态内部类,该内部类中的变量a 是被final修饰,说明变量a是不可变的,数据不可被修改

       /**
         * {@inheritDoc}
         *
         * <p>This implementation always throws an
         * {@code UnsupportedOperationException}.
         *
         * @throws UnsupportedOperationException {@inheritDoc}
         * @throws ClassCastException            {@inheritDoc}
         * @throws NullPointerException          {@inheritDoc}
         * @throws IllegalArgumentException      {@inheritDoc}
         * @throws IndexOutOfBoundsException     {@inheritDoc}
         */
        public void add(int index, E element) {
            throw new UnsupportedOperationException();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    其次,内部类ArrayList中并没有add的方法,而是使用了继承类AbstractList中add方法,该方法没有被重写,所以直接就抛了UnsupportedOperationException异常,正好对应上了

    直接使用new
     List<String> list= new ArrayList<>();
     list.add("王五");
    
    • 1
    • 2

    首先该ArrayList 是包java.util 下的类,虽然也继承了抽象类AbstractList,但是重写了抽象类AbstractList中的add方法

    /**
      * Appends the specified element to the end of this list.
      *
      * @param e element to be appended to this list
      * @return <tt>true</tt> (as specified by {@link Collection#add})
      */
     public boolean add(E e) {
         ensureCapacityInternal(size + 1);  // Increments modCount!!
         elementData[size++] = e;
         return true;
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    正是因为重写了add方法,所以才没有使用抽象类AbstractList中抛异常的add方法

    如何使用Arrays.asList创建的List可以正常执行add操作?

    上面分析了原因,因为Arrays中的静态内部类ArrayList未重写add方法,如果执行的add方法是重写后的,是否就可以解决? 可以将代码优化成下面的方式

    List<String> list1 = Arrays.asList("张三", "李四");
    try {
         list1.add("王五"); 
     } catch (UnsupportedOperationException e) {
         System.out.println("oh, 报错了=" + e.toString());
     }
    
     //改良方式
     List<String> list2 = new ArrayList<>(Arrays.asList("张三", "李四"));
     list2.add("王五");
     System.out.println("正常执行=" + list2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    执行效果
    在这里插入图片描述

  • 相关阅读:
    springboot @Validated的概念以及实战
    量子时代加密安全与区块链应用的未来
    【408数据结构与算法】—顺序表的插入、删除和查找(四)
    React + TypeScript 组件的状态和构造 React Hooks
    中科大郑烇、杨坚 《计算机网络》第三章: 传输层
    装配焊接工序模型创建wave关系的函数
    matplotlib详细教学
    本地vscode安装GPU版本PyTorch
    TreeMap类的继承关系简介说明
    DVWA-XSS(DOM)Low/Medium/High低中高级别
  • 原文地址:https://blog.csdn.net/weixin_44167408/article/details/132607589