arrays.aslist 返回固定大小、共享引用的可变视图,非真正不可变;list.of(jdk 9+)才是语义清晰、完全不可变的只读集合,适用于明确永不变更的场景。

Arrays.asList 本身不创建新数组,只是返回一个轻量级视图,因此创建开销极小;但它不是真正意义上的不可变集合,而是一个“固定大小、共享引用”的包装类——这点常被误认为是不可变集合,实则存在修改风险和语义混淆。
Arrays.asList 不等于不可变集合
它底层是 Arrays 的私有静态类(非 java.util.ArrayList),支持 set、get、indexOf 等读写操作,但 add/remove/clear 会直接抛 UnsupportedOperationException。更重要的是:它与原始数组双向绑定,改 list 某个元素,原数组对应位置也变;改数组,list 同样可见变化。这不是安全的不可变,而是受限的可变视图。
List.of 才是真正的不可变集合(JDK 9+)
它在创建时就做校验:任意元素为 null 就立即报 NullPointerException;创建后所有修改方法(包括 set、add、remove、clear,甚至 replaceAll)全部抛异常。内存结构更紧凑,无额外代理层,性能略优于 Arrays.asList(差异微乎其微,但语义更干净)。
- 适合配置项、枚举值列表、函数式参数等明确“只读且永不变更”的场景
- 不能用于需要后续添加元素的流程,哪怕只加一个也不行
- 不兼容 JDK 8 及以下版本,硬迁会导致编译失败
高频误用:把 Arrays.asList 当作安全只读集合
很多代码用 Collections.unmodifiableList(Arrays.asList(arr)) 套两层,以为更安全——其实多余。Arrays.asList 本身就不支持增删,再套一层只是增加对象创建开销,没提升安全性。真要只读且解耦,直接用 List.of;真要可变,就别绕弯,new ArrayList(Arrays.asList(arr)) 或用 Collections.addAll。
- 如果原始数组后续还会被其他逻辑修改,用 Arrays.asList 就可能引发隐蔽 bug
- 若只是临时传参给接收 List 的方法,且确定不增删,Arrays.asList 足够,无需升级
- 流式处理中,JDK 11 的 Stream.toList() 返回的是不可变 List(非 List.of,但行为一致),比 Collectors.toList() + unmodifiable 更简洁
基本类型数组的特殊陷阱
int[] arr = {1,2,3}; List
- 用 IntStream.of(arr).boxed().collect(Collectors.toList())
- 或手动循环:new ArrayList
(arr.length); for (int i : arr) list.add(i); - List.of 不接受基本类型数组,同样会编译失败
这个环节没有银弹,选哪种取决于你是否在流式链路里、是否在意装箱开销、以及 JDK 版本。











