Java数组clone()仅为浅拷贝,仅复制容器地址;深拷贝需元素类自身支持递归克隆,如Person类重写clone()并逐字段深拷贝引用对象,否则修改副本会影响原数组。

Java 数组本身支持 clone(),但这个操作只是浅拷贝——它复制数组容器,不复制里面对象的内容。要真正隔离修改、实现对象数组的深拷贝,不能只靠数组自身的 clone(),必须深入处理每个元素的引用关系。
数组 clone() 的本质是“地址复制”,不是“对象复制”
无论 String[] 还是 Person[],调用 arr.clone() 后:
- 新旧数组内存地址不同(
copy != original成立) - 但所有元素仍指向同一堆对象(
copy[0] == original[0]为 true) - 修改
copy[0].name会同步反映在original[0].name上
深拷贝的关键不在数组,而在元素类是否支持递归克隆
数组只是容器,真正决定能否深拷贝的是其元素类型。只有当每个对象自身能生成独立副本,整个数组才算深拷贝成功:
- 元素是不可变类型(如
String、Integer):无需深拷贝,Arrays.copyOf()或clone()即可满足业务需求 - 元素是自定义可变类(如
Person):该类必须正确实现深克隆逻辑,即重写clone()并对每个可变引用字段(如address、hobbies)也调用其clone() - 验证方式简单直接:改完副本中某个对象的字段后,立刻读原数组对应位置对象的同字段——值未变,才算深拷贝成功
手动遍历 + 元素 clone() 是可控场景下的首选方案
适用于已规范实现 Cloneable 和深克隆逻辑的类。核心不是“循环调用 clone”,而是确保每个 clone() 内部递归处理了全部引用字段:
立即学习“Java免费学习笔记(深入)”;
- 声明类实现
Cloneable - 重写
public Person clone(),调用super.clone() - 对每个引用字段(如
this.address)显式调用this.address.clone()并赋值给克隆体 - 数组层代码简洁:
Person[] copy = new Person[src.length]; for (int i = 0; i
替代方案需权衡适用边界
当无法修改元素类源码,或结构嵌套复杂时,可考虑其他路径,但各有前提:
- 序列化/反序列化:要求所有元素及内部字段类型都实现
Serializable,无 transient 敏感字段,且性能开销明显 - JSON 工具(如 Jackson):依赖字段可 public 或有 getter/setter,不支持私有 final 字段或含循环引用的对象,可能丢失类型信息
- Apache Commons Lang 的
ArrayUtils.deepClone():对常见 JDK 类型做了适配,但对自定义类仍需保证其可克隆或可序列化


















