arrays.aslist() 返回的是 arrays$arraylist 视图而非 arraylist,不支持 add/remove,修改影响原数组,原始类型数组会被整体封装,需用包装类或 stream 转换,可变操作须 new arraylist 包装。

Arrays.asList 不是“转成 ArrayList”,而是生成一个基于原数组的固定大小视图。用错场景会直接抛 UnsupportedOperationException,但只要清楚它能做什么、不能做什么,就能安全高效地用好。
它返回的不是 java.util.ArrayList
调用 Arrays.asList() 得到的是 java.util.Arrays$ArrayList(Arrays 的静态内部类),不是你日常用的 java.util.ArrayList。这个类继承自 AbstractList,只实现了 get、set、contains 等读写已有元素的方法,但没重写 add、remove、clear —— 所以一调就崩。
- 打印
list.getClass()会看到:class java.util.Arrays$ArrayList - 它支持随机访问(实现
RandomAccess)和序列化,适合做只读或仅修改内容的场景 - 它不扩容、不缩容,大小完全由传入数组长度决定
基本类型数组会“整个当一个元素”
传 int[]、double[] 这类原始类型数组时,泛型擦除机制会让整个数组被当作单个对象塞进 List:
-
int[] arr = {1, 2, 3}; List list = Arrays.asList(arr);→list.size()是 1,list.get(0)就是那个int[]对象本身 - 正确做法:用包装类数组,比如
Integer[] arr = {1, 2, 3};,或走 Stream:Arrays.stream(arr).boxed().collect(Collectors.toList())
数组和 List 共享底层数据
这个 List 是原数组的“适配器视图”,二者指向同一块内存:
-
String[] arr = {"a", "b"}; List<string> list = Arrays.asList(arr); list.set(0, "x");</string>→arr[0]立刻变成"x" - 反过来改数组,List 也会同步变;多线程环境下必须加同步,否则数据可能不一致
- 这种双向联动适合初始化后只读、或明确需要联动修改的场景(如配置项映射)
需要可变集合?必须“包一层”
如果后续要 add/remove/扩容,唯一稳妥做法是用它初始化一个新的 ArrayList:
- 推荐写法:
new ArrayList(Arrays.asList("a", "b", "c")) - 等价于:先建不可变视图,再拷贝进新容器——既保留语法简洁性,又获得完整集合能力
- 避免任何直接对
Arrays.asList()结果调用结构性方法,哪怕只有一行,线上出问题很难排查
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











