如下代码:
public static void main(String[] args) {
String[] strings = "qqq,www,eee,rrr".split(",");
List<String> strList = Arrays.asList(strings);
strList.add("ttt"); //java.lang.UnsupportedOperationException
strList.remove("eee"); //java.lang.UnsupportedOperationException
Iterator<String> it = strList.iterator();
while (it.hasNext()) {
if ("www".equals(it.next())) {
it.remove(); //java.lang.UnsupportedOperationException
}
}
}
出现异常:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
异常分析:
通过源码可以发现,Arrays.asList()
返回的是Arrays
的静态内部类java.util.Arrays.ArrayList
而不是java.util.ArrayList
!!!
不管是哪个ArrayList
,都继承于抽象类abstractList
,源码中可以看到add
、remove
方法是在抽象类abstractList
中定义,方法内容是抛出一个UnsupportedOperationException
异常。
继续去对比两个不同的ArrayList
可以发现,
java.util.ArrayList
继承了abstractList
并重写了add
、remove
等相关方法;而java.util.Arrays.ArrayList
继承了abstractList
却并没有进行重写。
回到第二张图,可以发现:Arrays
的静态内部类java.util.Arrays.ArrayList
定义的是一个final
修饰的不可变数组,一旦初始化后,这个数组的长度就是固定的,而这也是其不可进行add或remove的根本原因。
分析到此异常原因应该已然明了了。对于Iterator
的remove
方法抛出该异常的原因也是同理。
alibaba的代码规范检查中有如下这句话:
解决方法:
String[] strings = "qqq,www,eee,rrr".split(",");
List<String> strList = new ArrayList<>(Arrays.asList(strings));
说到 Arrays.asList,便也顺便提一嘴。
在只传一个参数的情况下,IDEA会建议你使用 Collections.singletonList()
代替Arrays.asList()
。如下图。
两者主要有两点区别:
- Collection.singletonList 长度为 1,只存储一个元素;Arrays.asList 可存储多个元素。
- Collection.singletonList 初始完后不可修改【添加、移除、修改均不支持】;Arrays.asList 初始完后数组长度固定,但元素可修改【添加、移除不支持,支持修改值(set方法)】。