Arrays.asList() 返回固定大小的不可变视图,不支持增删;拒绝基本类型数组;与原数组共享内存。需注意 null 数组 NPE、多线程竞态等问题。

Arrays.asList() 是 Java 中最常用的数组转列表工具,但它不是“万能转换器”,而是一个有明确边界的设计产物。用对了省事高效,用错了 runtime 报错、数据错乱、线上故障都可能发生。核心就三点:它返回的是固定大小的视图,不支持增删;它拒绝基本类型数组;它和原数组共享内存。
Arrays.asList 返回的是不可变视图,不是 ArrayList
它返回的类名虽叫 ArrayList,但实际是 java.util.Arrays$ArrayList(Arrays 的私有内部类),不是你日常使用的 java.util.ArrayList。这个类继承 AbstractList,只实现了 get/set/contains 等读写单个元素的方法,但 add/remove/clear 全部抛 UnsupportedOperationException。
- 错误写法:
list.add("x")→ 运行时直接崩溃 - 安全写法:需要增删时,必须包装一层 ——
new ArrayList(Arrays.asList(arr)) - 只读场景(如传参、遍历、查找)可直接用,无需额外拷贝,性能更好
基本类型数组会被整体当做一个元素
泛型机制要求 T 是引用类型,int[]、double[] 等本身是对象,但不是 Integer[] 的子类型。所以传入 int[]{1,2,3},结果是 size=1、get(0) 返回整个 int[] 数组对象,而非三个 Integer 元素。
- 典型表现:
System.out.println(Arrays.asList(new int[]{1,2,3}).size()); // 输出 1 - 正确做法一:改用包装类数组 ——
Integer[] arr = {1,2,3}; Arrays.asList(arr) - 正确做法二(Java 8+):用 Stream 装箱 ——
Arrays.stream(arr).boxed().collect(Collectors.toList())
数组与列表内容双向同步,修改任一端另一端立即可见
asList 返回的列表底层直接持有所传数组的引用,set 操作等价于数组赋值,数组改动也会反映在列表上。这不是 bug,而是“视图”设计的本意。
立即学习“Java免费学习笔记(深入)”;
- 示例:
String[] a = {"a","b"}; List<String> l = Arrays.asList(a); l.set(0, "z"); → a[0] 变为 "z" - 若需解耦,必须创建副本:用
new ArrayList(Arrays.asList(arr))或先arr.clone()再 asList - 多线程环境下尤其危险——无内置同步,共享数组 + 视图极易引发竞态
别忘了 null 数组会直接 NPE
Arrays.asList(null) 不做空检查,内部直接用 null 初始化,后续调用 size() 或 iterator() 都会触发 NullPointerException。
- 高危场景:从配置、接口或用户输入获取数组后未判空就直接 asList
- 安全写法:
List<String> list = arr == null ? Collections.emptyList() : Arrays.asList(arr); - 框架层建议:封装工具方法时,统一加 null guard,避免下游反复处理


















