Arrays.asList()和Collection.toArray()不能乱用,因基本类型数组、泛型擦除、结构性修改三类问题易致UnsupportedOperationException或ClassCastException。

直接说结论:Arrays.asList() 和 Collection.toArray() 都不能“图省事”地乱用,基本类型数组、泛型擦除、结构性修改这三类问题踩中任意一个,就可能在运行时抛 UnsupportedOperationException 或 ClassCastException。
Arrays.asList() 为什么不能对基本类型数组调用
因为 Arrays.asList(new int[]{1, 2, 3}) 不会返回 List,而是返回只含一个元素(即那个 int[] 对象)的 List。编译器把整个数组当成了泛型参数 T 的一个实例,不是逐个装箱。
- 正确做法是先用包装类型数组:
Integer[] arr = {1, 2, 3}; Listlist = Arrays.asList(arr); - 更推荐用 Stream:
Listlist = Arrays.stream(new int[]{1, 2, 3}).boxed().collect(Collectors.toList()); - 别写
(List强转——编译能过,运行时类型不匹配) (List) Arrays.asList(...)
Arrays.asList() 返回的 List 为什么不能 add/remove
它返回的是 Arrays.ArrayList(注意:不是 java.util.ArrayList),这个内部类继承自 AbstractList,而后者所有结构性修改方法(add、remove、clear)都直接抛 UnsupportedOperationException。
- 如果后续要增删,请立刻包一层:
new ArrayList(Arrays.asList(...)) - 别依赖注释或文档“提醒自己别改”,框架代码或协作方可能不知道这个限制
-
set()是允许的——它只是替换,不改变结构
集合转数组为什么必须传泛型数组,不能传 new Object[0]
list.toArray(new Object[0]) 看似能编译,但返回的是 Object[],丢失泛型信息;若强制转型为 String[],运行时大概率触发 ClassCastException。
- 正确写法只有两种:
list.toArray(new String[0])(推荐)或list.toArray(new String[list.size()]) - 传
new String[0]更安全:避免并发修改导致 size 失准;JVM 对空数组有优化,性能无差异 - 该规则适用于所有
Collection子类,包括Set、Deque,不只是List
什么时候该用 Guava 或 JDK9+ 替代原生工具类
当需要可变、安全、语义明确的构造行为时,原生 API 显得冗长且易错。
- 初始化不可变列表,优先用
List.of("a", "b")(JDK9+),而非Arrays.asList(...)+ 注释说明“勿修改” - 需要可变副本,用
Lists.newArrayList(...)(Guava),比new ArrayList(Arrays.asList(...))更直白 - 涉及基本类型批量操作,Guava 的
Ints.asList()、Ints.toArray()比手写 Stream 更简洁且零装箱开销
最常被忽略的一点:这些转换不是“语法糖”,而是涉及内存布局、泛型推导和运行时类型检查的真实操作。写完记得看一眼字节码或 debug 进去确认实际类型,别只信 IDE 的自动补全提示。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











