Java中重写clone()实现数组深拷贝的关键是:基本类型数组用super.clone()即可,引用类型数组需逐个克隆元素;若元素实现Cloneable则调用element.clone(),否则用构造器或序列化重建。

Java 中重写 clone() 实现数组的深拷贝,关键在于:数组字段不能直接调用 super.clone() 了事,必须对每个可变对象元素单独克隆;基本类型数组可直接克隆,引用类型数组需逐个克隆其元素。
区分数组类型:基本类型 vs 引用类型
基本类型数组(如 int[]、double[])本身不可变,super.clone() 已是深拷贝效果,无需额外处理。而引用类型数组(如 String[]、MyObj[])克隆后只是复制了引用,原数组和克隆数组指向同一堆内存中的对象——这是浅拷贝,必须手动深拷贝每个元素。
-
int[] data = {1, 2, 3};→int[] copy = data.clone();安全,互不影响 -
MyObj[] items = {new MyObj("a"), new MyObj("b")};→items.clone()后,copy[0]和items[0]仍指向同一个MyObj实例
重写 clone() 时正确处理引用类型数组
在自定义类的 clone() 方法中,先调用 super.clone() 得到新对象,再对引用类型数组字段逐一深拷贝。若数组元素类型实现了 Cloneable 并重写了 clone(),可用循环 + element.clone();否则需通过构造器、序列化或第三方库重建。
- 确保元素类支持克隆:例如
MyObj实现Cloneable,且public Object clone() { ... }返回正确类型 - 在容器类中这样写:
public MyClass clone() { try { MyClass cloned = (MyClass) super.clone(); if (this.objArray != null) { cloned.objArray = new MyObj[this.objArray.length]; for (int i = 0; i < this.objArray.length; i++) { cloned.objArray[i] = this.objArray[i].clone(); // 假设 MyObj.clone() 返回 MyObj } } return cloned; } catch (CloneNotSupportedException e) { throw new AssertionError(); // 不可能发生,因已实现 Cloneable } }
替代方案:避免 clone() 的更可靠做法
原生 clone() 机制脆弱(如未实现 Cloneable 抛异常、不支持 final 字段、继承链易出错),推荐更清晰可控的方式:
立即学习“Java免费学习笔记(深入)”;
- 提供显式拷贝构造器:
public MyClass(MyClass other) { this.objArray = copyArray(other.objArray); } - 提供静态工厂方法:
public static MyClass deepCopy(MyClass src) { ... } - 使用序列化(适用于可序列化类型):
new ObjectInputStream(new ByteArrayInputStream(serialized)).readObject() - 借助
Apache Commons Lang:SerializationUtils.clone(obj)或BeanUtils.cloneBean()(注意后者默认浅拷贝,需配合自定义转换器)
注意事项与常见陷阱
不要忽略 null 数组、空数组、嵌套结构(如二维数组 MyObj[][] 需两层循环)、不可变对象(如 String 数组虽是引用类型,但元素本身不可变,通常无需深拷贝元素)。
- 检查数组是否为
null,避免NullPointerException - 若数组含泛型(如
List<String>[]),需确保泛型元素也支持深拷贝逻辑 - 慎用
Arrays.copyOf():它对引用类型数组仍是浅拷贝,等价于clone() - 所有参与深拷贝的类都应明确文档说明“支持深拷贝”,并保证克隆逻辑一致性


















