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

早上到公司,刚到工位,测试同事就跑来说"功能不行了,报服务器异常了,咋回事";我一脸蒙,早饭都顾不上吃,要来了测试账号复现了一下,然后仔细观察测试服务器日志,发现报了一个java.lang.UnsupportedOperationException异常

经排查发现,是将一个枚举类中两个元素,用Arrays.asList生成一个List集合,并且将这个集合当作一个方法的参数传递,在该方法中,正好使用此List进行了add方法的操作,导致异常发生了

Arrays.asList

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

coffeescript 复制代码
 @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;
    }
.......... 省略,可自行去看源码....
}

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

coffeescript 复制代码
   /**
     * {@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();
    }

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

直接使用new

clike 复制代码
 List<String> list= new ArrayList<>();
 list.add("王五");

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

coffeescript 复制代码
/**
  * 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;
 }

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

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

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

clike 复制代码
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);

执行效果

相关推荐
芳草萋萋鹦鹉洲哦4 小时前
【vue3+tauri+rust】如何实现下载文件mac+windows
windows·macos·rust
李洋-蛟龙腾飞公司4 小时前
HarmonyOS NEXT应用元服务常见列表操作多类型列表项场景
windows
云泽野4 小时前
【Java|集合类】list遍历的6种方式
java·python·list
学不动CV了9 小时前
数据结构---线性表理解(一)
数据结构
new_zhou9 小时前
Windows qt打包编译好的程序
开发语言·windows·qt·打包程序
Rocket MAN9 小时前
Rovo Dev CLI Windows 安装与使用指南
windows
ysa0510309 小时前
数论基础知识和模板
数据结构·c++·笔记·算法
今天背单词了吗98010 小时前
算法学习笔记:7.Dijkstra 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·数据结构·笔记·算法
气质、小青年!10 小时前
【排序算法】
c语言·数据结构
clock的时钟12 小时前
暑期数据结构第一天
数据结构·算法