Java中Object类clone()默认浅拷贝,深拷贝需手动处理引用字段;须实现Cloneable接口、重写public clone()并调用super.clone();推荐链式克隆或改用拷贝构造器等更安全方式。

Java 中 Object 类的 clone() 方法默认只支持浅拷贝,要实现深拷贝需手动处理引用类型字段。关键在于理解 Cloneable 接口的作用、重写 clone() 的规范写法,以及如何识别并复制对象图中的引用关系。
浅拷贝:只需实现 Cloneable 并重写 clone()
浅拷贝仅复制对象本身(基本类型值直接复制,引用类型字段只复制地址,不创建新对象)。必须满足两个前提:
- 类需实现
Cloneable接口(空接口,仅作为标记) - 重写
public Object clone()方法,并调用super.clone()
示例:
public class Person implements Cloneable {
private String name;
private int age;
private Address address; // 引用类型
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); // 浅拷贝:address 字段仍指向原对象
}
}
此时修改克隆对象的 address 属性,会影响原对象——因为两者共用同一个 Address 实例。
立即学习“Java免费学习笔记(深入)”;
深拷贝:对每个引用字段递归 clone 或重新构造
深拷贝要求所有引用类型的字段也生成独立副本。常见做法有三种:
- 在 clone() 中手动 new 或 clone 每个引用字段:适用于字段数量固定、类型明确的场景
- 让引用字段所属类也实现 Cloneable 并重写 clone():形成链式克隆,更可维护
- 使用序列化/反序列化绕过 clone 机制:适合复杂对象图,但要求所有字段可序列化且性能略低
推荐方式(链式 clone):
public class Address implements Cloneable {
private String city;
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Person implements Cloneable {
private String name;
private int age;
private Address address;
@Override
public Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
cloned.address = (Address) this.address.clone(); // 深拷贝 address
return cloned;
}
}
注意 clone() 的访问权限与异常处理
Object.clone() 是 protected 方法,子类重写时应改为 public 才能被外部调用。同时必须声明抛出 CloneNotSupportedException,或在内部捕获处理(不推荐吞掉异常)。
- 不声明异常 → 编译报错
- 声明
throws CloneNotSupportedException→ 调用方必须处理 - 用 try-catch 包裹
super.clone()→ 可转为运行时异常或返回 null,但违背设计意图
替代方案:考虑是否真需要 clone()
现代 Java 开发中,clone() 因语义模糊、易出错(如忘记处理引用字段)、与继承配合不佳等问题,常被以下方式替代:
- 拷贝构造器:显式、类型安全、易于控制复制逻辑
-
静态工厂方法:如
Person.copyOf(person),语义清晰 - 不可变对象 + builder 模式:避免拷贝,通过新建实例组合数据
除非已有大量依赖 clone() 的旧代码,否则优先选择更直观、可控的复制方式。


















