如下代码:
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方法)】。
本文探讨了在Java中使用Arrays.asList()创建列表时遇到的UnsupportedOperationException异常,解释了原因——Arrays.ArrayList是不可变的。作者提供了使用new ArrayList<>()的替代方案,并对比了Collections.singletonList()的特性。关键词:Arrays.asList, ArrayList, 不可变数组, add/remove, Iterator
1672

被折叠的 条评论
为什么被折叠?



