java.lang.UnsupportedOperationException原因分析及解决
前言
今天搬砖时,在使用Array.asList把数组转化 为list时,在对转化的list添加删除数据时,出现了java.lang.UnsupportedOperationException异常信息。
一、原因分析
首先来看下面的代码。
List<String> list = Arrays.asList("Kobe", "Mamba out");
list.add("Mamba never out!");
list.forEach(System.out::println);
看着上面的代码,一切都显得那么合理,那么的理所当然,然鹅点击运行,what? 居然出现了以下的异常信息;
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at com.ac.question.QuestionApplication.main(QuestionApplication.java:44)
UnsupportedOperationException这又是什么异常?本着遇到问题不要慌,先看看源码的原则。打开了Arrays.asList的源码,首先在数组转化为list的时候没有报错,那就是在执行list.add方法的时候出现了错误,所以看看源码中这个转化过程中都发生了什么。
可以看到Arrays.asList使用过新建一个ArrayList类来实现的,接下来我们继续看ArrayList。
通过上面的图片我们可以看到,这里的ArrayList并不是我们平时使用的ArrayList,这里的ArrayList是Arrays自己定义的一个内部类,OK初步判断问题肯定是出现在这个类上,我们继续向上寻找,继续看它的父类AbstractList的源码。
在AbstractList这个类中我们找到添加元素的add的方法,如上图所示,可以看到这里并没有实现添加数据的逻辑,而是直接抛出了异常信息。通过该源码我们可以知使用Arrays.asList()方法创建的list,并不支持对数据的更改操作。
二、Arrays中其他的坑
1.将基本类型作为asList的参数
我们先来看一段代码,下面代码的输出结果是什么?
int[] array = new int[]{1,2,1,2,1,2};
List list = Arrays.asList(array);
System.out.println(list.size());
控制台打印的结果为1,因为在Arrays类的内部,ArrayList的构造方法接收一个类型为T的数组,而基本类型是不能作为泛型参数的,所以这里的参数只能接收引用类型,而编译器在编译的时候把int[]数组当成了一个引用参数,所以最后程序的输出结果为1。修改方法因为基本类型不能作为泛型参数,所以把int[]修改成Integer[]即可。
2.asList转化后修改其中的值
再来看下面这样一段代码,输出的结果又是什么?
String[] array = {"Kobe","James","Jordan"};
List list = Arrays.asList(array);
array[1] = "Mamba out!";
list.set(2,"Mamba never out!");
System.out.println(Arrays.toString(array));
System.out.println(list.toString());
输出结果为:
[Kobe, Mamba out!, Mamba never out!]
[Kobe, Mamba out!, Mamba never out!]
由于asList产生的集合元素是直接引用作为参数的数组,所以当外部数组或集合改变时,数组和集合会同步变化。