关于在使用List的remove方法的时候报下列错误的一个记录(自己写的一个Demo来复现问题)
异常信息:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at cn.vjsp.user.util.ListDemo.test(ListDemo.java:20)
at cn.vjsp.user.util.ListDemo.main(ListDemo.java:11)
java.lang.UnsupportedOperationException
1、异常出现的场景
先上代码
static void test(List<Integer> firstList){}
场景: 提供一个方法,入参是一个List(我们所认为的一个List),然后我们处理完业务逻辑后,要将处理过后的数据从List中移除,调用List的remove方法然后将剩余的数据返回,但是我们发现在调用的时候报异常信息了UnsupportedOperationException,其实我们都知道,remove方法就是List的,但是怎么会报错呢?请看下列分析
2、查看入参firsList的类型
static void test(List<Integer> firstList){
System.out.println("******** firstList.class = " + firstList.getClass());
}
输出结果:
******** firstList.class = class java.util.Arrays$ArrayList
分析: 从上面拿到的 firstList 类型我们可以看到,它的类型是Arrays 类下的ArrayList 内部类,接下来我们继续看Array 的源码。
3、Arrays源码分析
直接看Arrays的源码,上图是Arrays的静态内部类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);
}
通过我们第二步里面拿到的 firstList 的类型(class java.util.Arrays$ArrayList),找到它所在的源码,发现该静态内部类是继承自AbstractList ,所以我们继续往下走,查看AbstractList 的源码。
4、AbstractList源码分析
直接上图
然后我们就发现,AbstractList是实现了List接口的,既然实现了List接口,那么肯定有remove 方法吧?恭喜你,猜对了,确实有remove方法
那么既然有remove方法,我们就看看remove方法咋写的吧,为啥会抛出那个异常信息呢?
惊不惊喜,意不意外,人家AbstractList 压根就没重写remove 方法,直接给你抛出一手异常信息,刺激不,这就是你为啥调用remove 方法的时候会报错了,这就是原因,了解了么
5、另外一种解释
① Arrays是数组,大小不可变,当我们去修改大小不可变的列表时,会抛出 UnsupportedOperationException这个异常
② 而我们日常所见到的那个单独的java.util.ArrayList它返回的是一个可变列表,它是支持我们去对列表进行相应的修改操作
总结
综上所述,当我们碰到这个异常信息的时候,大概率就是因为我们所见到的那个List 并不是我们想要的那个List,此时,我们可以看看它的类型,这样大概率就会找到原因所在。