Arrays.copyOf适用于完整拷贝、扩容或缩容,自动创建新数组并填充默认值;System.arraycopy适用于高性能部分拷贝或原地移动,要求目标数组已存在且需手动校验边界。

Java 拷贝数组没有“万能解”,但有清晰的选型逻辑:优先用 Arrays.copyOf() 或 System.arraycopy(),按场景选;避免直接赋值或裸 clone() 带来的隐式共享风险。
一、完整拷贝或扩容 → 用 Arrays.copyOf()
这是最常用、语义最清晰的方式。它内部调用 System.arraycopy(),封装了目标数组创建逻辑,省去手动 new 数组的步骤。
- 完整复制:
int[] copy = Arrays.copyOf(src, src.length); - 扩容复制(自动填充默认值):
String[] bigger = Arrays.copyOf(src, 10);—— 多余位置填null - 缩容复制(截断):
int[] smaller = Arrays.copyOf(src, 3);—— 只取前 3 个元素
适用于 DTO 转换、参数备份、缓存快照等需独立副本的常规场景。对基本类型和不可变对象(如 String)安全有效。
二、高性能部分拷贝或原地重排 → 用 System.arraycopy()
它是 JVM 底层内存搬运指令的 Java 封装,零对象构造开销,性能最优,且支持跨数组/同数组内任意区域搬移。
立即学习“Java免费学习笔记(深入)”;
- 跨数组复制:
System.arraycopy(src, 2, dest, 0, 3);—— src[2..4] → dest[0..2] - 同数组左移(安全):
System.arraycopy(arr, 3, arr, 0, 5);—— 等效于删除前 3 个元素后前移 - 同数组右移(需注意顺序):
System.arraycopy(arr, 0, arr, 3, 5);—— JVM 自动倒序执行,避免覆盖
适合高频调用、算法实现(如滑动窗口)、环形缓冲区管理等对性能敏感的场景。务必校验边界:srcPos + length ≤ src.length,destPos + length ≤ dest.length。
三、对象数组深拷贝 → 不靠 Arrays.copyOf(),要分层处理
Arrays.copyOf() 对 Person[] 这类数组只复制引用,不是真正深拷贝。修改副本中的 Person 实例,仍会影响原数组。
- 若元素类已实现
Cloneable且正确重写clone():
遍历 + 元素克隆:copy[i] = (Person) src[i].clone(); - 若结构复杂(含集合、嵌套对象、循环引用):
用序列化反序列化(要求所有字段可序列化)
或引入 MapStruct/Lombok @Builder 等结构化转换工具,显式定义映射规则
防御性拷贝必须明确“深”到哪一层。业务层通常只需浅拷贝数组壳 + 深拷贝关键可变字段(如 Date、List),而非无脑全递归。
四、简洁完整拷贝 → clone() 可用,但需谨慎
数组是唯一天然支持 .clone() 的 Java 类型,语法最简:int[] copy = src.clone();
- 优点:代码少、性能好、无需导入、对基本类型和不可变对象数组完全安全
- 缺点:无法指定长度(只能等长)、不支持部分拷贝、对对象数组仍是浅拷贝
- 适用:单元测试中快速造数据、工具方法内临时副本、明确知道元素不可变时
不推荐在核心业务逻辑中无条件使用,尤其当数组类型为泛型对象数组时,易埋下共享状态隐患。
不复杂但容易忽略:拷贝目的决定方式。只是隔离数组容器?用 copyOf 或 clone。需要移动数据块?用 arraycopy。要切断对象引用链?得进到元素层面做控制。


















