Arrays.asList返回的是不可变的Arrays$ArrayList视图,调用add()等修改结构的方法会抛UnsupportedOperationException;正确做法是new ArrayList<>(Arrays.asList(arr))创建可变副本。

Arrays.asList 是 Java 中最常用的数组转列表方法,但它不是“万能转换器”,用错容易在运行时抛出 UnsupportedOperationException。关键在于理解它返回的不是 java.util.ArrayList,而是 java.util.Arrays$ArrayList——一个绑定原数组、大小固定、只读结构的视图。
为什么调用 add() 会报错?
Arrays.asList 返回的内部类 Arrays$ArrayList 持有 final E[] a 引用,完全复用原始数组内存。它继承 AbstractList,而 AbstractList 的 add() 和 remove() 方法默认直接抛异常:
- public void add(int index, E element) { throw new UnsupportedOperationException(); }
- 该设计是 JDK 明确行为,不是 bug,目的是保证“列表结构 = 数组结构”严格一致
- 哪怕 list.add("x") 这样一行代码,也会在运行时报错
哪些操作能用?哪些不能?
允许的操作(安全):
- get()、set()、size()、contains()、indexOf()、toArray()
- set(index, e) 可修改已有位置的值,且同步更新原数组对应元素
- toArray() 返回原数组副本,不破坏原始数据
禁止的操作(会抛异常):
立即学习“Java免费学习笔记(深入)”;
- add()、addAll()、remove()、clear()、retainAll()
- 任何改变集合长度或结构的操作均不支持
基本类型数组的陷阱
int[]、double[] 等传给 Arrays.asList 时,会被整体当作一个对象处理:
- int[] arr = {1, 2, 3}; List list = Arrays.asList(arr); → list.size() == 1,元素类型是 int[]
- 正确做法:改用 Integer[],或用 Stream 装箱:Arrays.stream(arr).boxed().collect(Collectors.toList())
如何获得真正可修改的 ArrayList?
必须创建新实例,不能绕过限制:
- 推荐写法:new ArrayList(Arrays.asList(arr)) —— 安全、语义清晰、兼容所有 JDK 版本
- Java 8+ 可选:Arrays.stream(arr).collect(Collectors.toList())(JDK 16+ 返回可变 ArrayList)
- 避免使用 List.copyOf()(Java 10+),它返回不可变集合,同样不支持 add


















