实现克隆需实现Cloneable接口并重写clone()方法,1. 默认为浅克隆,仅复制基本类型和引用地址;2. 深克隆需手动复制引用对象;3. 推荐使用拷贝构造函数或序列化替代以避免问题。

在Java中实现对象的克隆功能,核心方式是通过实现 Cloneable 接口并重写 Object 类中的 clone() 方法。虽然Java提供了原生支持,但使用时需要注意深拷贝与浅拷贝的区别,以及正确处理可变字段。
启用克隆:实现 Cloneable 接口
Cloneable 是一个标记接口,不包含任何方法。实现该接口的作用是向 JVM 表明该类允许被克隆。如果不实现它,调用 clone() 方法会抛出 CloneNotSupportedException。
基本步骤如下:
- 让类实现 Cloneable 接口
- 重写 Object 的 clone() 方法,并将其访问级别改为 public
- 在方法内部调用 super.clone()
public class Person implements Cloneable {
private String name;
private int age;
@Override
public Person clone() {
try {
return (Person) super.clone();
} catch (CloneNotSupportedException e) {
throw new AssertionError(); // 不应发生
}
}
}
浅克隆 vs 深克隆
默认的 clone() 方法执行的是浅克隆,即只复制对象的基本类型字段和引用地址,而不复制引用对象本身。如果原对象包含其他对象(如数组、集合、自定义对象),克隆后的新对象将共享这些引用。
立即学习“Java免费学习笔记(深入)”;
若需要完全独立的副本,必须实现深克隆。
- 浅克隆问题示例:两个对象共用同一个地址对象,修改一个会影响另一个
- 解决办法:在 clone() 方法中手动克隆引用类型的字段
public class Person implements Cloneable {
private String name;
private Address address; // 假设 Address 也可克隆
@Override
public Person clone() {
try {
Person cloned = (Person) super.clone();
cloned.address = this.address.clone(); // 假设 Address 也实现了 clone
return cloned;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
}
}
}
替代方案:构造函数或序列化
除了 clone(),还有更安全、清晰的方式创建对象副本:
- 拷贝构造函数:public Person(Person other) { ... }
- 工厂方法:如 from(person)
- 序列化反序列化:适用于复杂对象且所有字段都可序列化的情况
这些方法避免了 clone() 的诸多陷阱,比如保护性拷贝缺失、构造器未执行等问题。
基本上就这些。Java 的 clone 机制虽然存在,但使用需谨慎。推荐优先考虑拷贝构造函数或现代序列化工具(如 Jackson、JSON 序列化)来实现对象复制,代码更清晰且不易出错。










