Arrays.asList返回的列表不支持add、remove、clear等结构性操作,因其是Arrays内部私有静态类ArrayList,直接绑定原数组且未重写这些方法,调用时抛UnsupportedOperationException;正确做法是new ArrayList<>(Arrays.asList(arr))创建可变副本。

Arrays.asList 返回的不是真正可变的 ArrayList,而是 Arrays 内部的一个私有静态类(也叫 ArrayList,但和 java.util.ArrayList 完全不同),它直接包装原始数组,不支持 add、remove、clear 等结构性操作——调用就会抛 UnsupportedOperationException。这不是 bug,是设计使然,但极易在开发中误用引发线上异常。
哪些操作会触发 UnsupportedOperationException?
只要改变列表“结构”(即元素个数)的操作都会失败:
-
list.add("x")、list.addAll(otherList) -
list.remove(0)、list.remove("a") list.clear()-
list.retainAll(filter)、list.removeAll(toRemove) -
list.replaceAll(...)(JDK 11+,底层未重写时同样报错)
为什么看似能 set 却不能 add?
这个内部 List 支持 get() 和 set(),因为它们只是读写原数组对应下标位置——数组长度固定,所以改值没问题;但 add() 需要扩容,而原数组无法动态伸缩,方法又没被重写,只能沿用 AbstractList 的默认实现,直接抛异常。
换句话说:它允许「改内容」,不允许「改容量」。
立即学习“Java免费学习笔记(深入)”;
如何快速识别并修复问题?
排查时重点看三处:
- 堆栈是否指向 AbstractList.add / .remove —— 这是典型 asList 陷阱标志
-
上游是否用了基本类型数组,例如
Arrays.asList(new int[]{1,2,3})→ 实际得到的是List<int></int>(只含一个元素),后续任何操作都偏离预期 - 是否误以为 list.set() 安全就忽略共享引用风险:修改 list 元素会同步改原数组,其他线程或模块若也在操作该数组,就会出现“数据莫名变更”
推荐的正确写法
根据 JDK 版本和场景选择:
- 需要可变列表且兼容 JDK 7+:
new ArrayList(Arrays.asList(arr)) - JDK 10+ 且想语义更清晰:
new ArrayList(List.of("a", "b", "c")) - 处理基本类型数组(如 int[]):
Arrays.stream(arr).boxed().collect(Collectors.toCollection(ArrayList::new)) - 纯只读场景、追求轻量:
List.of("a", "b", "c")(不可变,线程安全)


















