Java中对象拷贝需实现Cloneable接口并重写public clone()方法:浅拷贝调用super.clone()即可,引用字段共享;深拷贝须手动克隆每个可变引用字段,且被引用类也需支持克隆。

Java 中通过实现 Cloneable 接口并重写 clone() 方法,可以实现对象拷贝。但需注意:默认只支持浅拷贝,深拷贝需手动处理引用类型字段。关键在于理解两者的区别、正确声明接口、重写方法,并对可变引用类型做额外复制。
浅拷贝:只需实现 Cloneable + 重写 clone()(调用 super.clone())
浅拷贝会复制对象本身,但其内部的引用类型字段仍指向原对象的同一块堆内存。适用于对象中所有字段都是基本类型或不可变类型(如 String、Integer),或你明确希望共享引用。
- 必须实现
Cloneable接口(空标记接口,不提供任何方法);否则调用clone()会抛CloneNotSupportedException -
clone()方法需声明为public(父类中是protected),并调用super.clone() - 基本类型和不可变对象自动完成“值复制”,无需额外操作
public class Person implements Cloneable {
private String name;
private int age;
private Address address; // 引用类型
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
public Person clone() {
try {
return (Person) super.clone(); // 浅拷贝:address 字段仍指向原对象
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
深拷贝:在浅拷贝基础上,手动克隆每个可变引用字段
深拷贝要求对象及其所有引用类型的字段(尤其是可变对象)都创建独立副本。若引用类型也实现了 Cloneable,可在 clone() 中调用其 clone();否则需通过构造函数、工厂方法或序列化等方式新建实例。
- 先调用
super.clone()获取本对象副本 - 对每个可变引用字段(如
Address),单独调用其clone()或构造新对象并复制内容 - 确保被引用类也支持克隆(实现
Cloneable并重写clone())
public class Address implements Cloneable {
private String city;
public Address(String city) { this.city = city; }
@Override
public Address clone() {
try {
return (Address) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
// Person.clone() 改为:
@Override
public Person clone() {
try {
Person cloned = (Person) super.clone();
cloned.address = this.address.clone(); // 深拷贝 address
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
注意事项与常见陷阱
-
Cloneable是标记接口,不强制定义clone(),因此子类必须显式重写,且不能依赖多态自动调用 - 数组类型字段(如
int[]、String[])调用super.clone()会得到新数组,但数组元素仍是浅拷贝——基本类型没问题,引用类型仍需逐个克隆 - 若类含 final 字段,且该字段是可变引用类型,则无法在
clone()中重新赋值(final 不允许修改),此时应避免使用 clone,改用构造器或 builder 模式 - 继承体系中,父类未正确实现克隆时,子类
super.clone()可能返回不符合预期的对象,建议每层都自行处理关键字段
替代方案:为什么很多人不用 clone()
由于 Cloneable 设计存在缺陷(语义模糊、异常繁琐、破坏封装),现代 Java 开发更倾向以下方式:
- 拷贝构造器:`public Person(Person other)`,逻辑清晰、类型安全、支持 final 字段
- 静态工厂方法:如 `Person.copyOf(other)`,命名明确、可返回子类型
-
序列化/反序列化(适用于可序列化对象):借助
ObjectOutputStream实现天然深拷贝,但性能低、要求所有字段可序列化 -
第三方库:如 Apache Commons Lang 的
SerializationUtils.clone()或 MapStruct 等代码生成工具










