Arrays.copyOf() 创建新数组并复制内容,不改变原数组长度;必须显式赋值才能更新引用,且对泛型数组需用带Class参数的重载避免ClassCastException。

Arrays.copyOf() 不是“扩容”原数组,而是创建一个新数组并复制内容——原数组对象本身不可变,这点必须先明确。想靠它“改变原数组长度”却忘了重新赋值给变量,是绝大多数人踩的第一个坑。
为什么 Arrays.copyOf() 返回新数组而不是修改原数组
Java 中数组是对象,但其长度在创建后就固定了。Arrays.copyOf() 底层调用的是 System.arraycopy(),它只能把旧数组的内容拷贝到另一个(可能更大或更小)的数组里。所以它必须返回新数组引用,由你决定是否用它覆盖原来的变量。
- 常见错误现象:
int[] arr = {1,2}; Arrays.copyOf(arr, 5);执行完arr还是长度为 2,没变 - 正确做法:必须显式赋值,如
arr = Arrays.copyOf(arr, 5); - 参数差异:
copyOf(T[] original, int newLength)只控制目标长度;若newLength < original.length,则截断;若更大,则补默认值(0、null、false)
复制时类型擦除导致的 ClassCastException 风险
泛型数组 + Arrays.copyOf() 容易翻车。比如你写 List<String>[] lists = new ArrayList[3];,然后想扩容:lists = Arrays.copyOf(lists, 5); —— 看似没问题,但运行时可能抛 ClassCastException,因为 copyOf() 对泛型数组实际生成的是 Object[],再强转失败。
- 根本原因:Java 泛型擦除后,
Arrays.copyOf()无法得知原始泛型类型,只能按Object[]处理 - 安全替代:对泛型数组,优先用
Arrays.copyOf(T[] original, int newLength, Class<? extends T[]> newType)重载,例如:lists = Arrays.copyOf(lists, 5, ArrayList[].class); - 性能影响:带
Class参数的版本会多一次类型检查和数组创建,但避免了运行时异常,值得
和 System.arraycopy() 比,什么情况下该选 copyOf()
两者都快,但语义和使用场景不同。System.arraycopy() 是底层拷贝指令,需要手动分配目标数组;copyOf() 封装了分配+拷贝两步,更简洁,适合“我要一个指定长度的新副本”这种需求。
- 用
copyOf():快速得到一个等长/更长/更短的副本,比如扩容缓存数组、截取前 N 个元素 - 用
System.arraycopy():已有目标数组、需部分拷贝(如从索引 2 开始拷 5 个)、或性能极致敏感(省掉一次 new 数组开销) - 兼容性注意:
copyOf()在 Java 6+ 可用;System.arraycopy()更老,但写法略啰嗦
真正容易被忽略的是:当原数组为 null 时,Arrays.copyOf(null, N) 会直接抛 NullPointerException,它不做空保护——如果你的输入可能为空,得自己加判空逻辑,而不是指望这个方法兜底。

















