Java中Object.clone()默认只支持浅拷贝,深拷贝需手动克隆引用类型字段;启用clone需实现Cloneable接口并重写public clone()方法调用super.clone();深拷贝要求所有引用字段独立,被引用类也须可克隆;生产中更推荐拷贝构造器、静态工厂或序列化等替代方案。

Java 中 Object.clone() 默认只支持浅拷贝,要实现深拷贝需手动处理引用类型字段 —— 这是理解 clone 机制的关键。
浅拷贝:默认行为,只复制对象本身
调用 clone() 时,JVM 会创建一个新对象,并将原对象的**基本类型字段值直接复制**,**引用类型字段的地址值也直接复制**(即两个对象的引用字段指向同一堆内存中的对象)。
要启用 clone(),类必须:
- 实现
Cloneable接口(标记接口,不包含方法) - 重写
clone()方法,并将访问修饰符改为public - 在方法内调用
super.clone()
示例:
立即学习“Java免费学习笔记(深入)”;
String name;
Address address; // 引用类型
public Person clone() {
try {
return (Person) super.clone(); // 浅拷贝:address 字段地址被复制
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}
深拷贝:需手动克隆所有引用字段
深拷贝要求新对象及其**所有引用类型的字段都独立于原对象**。仅靠 super.clone() 不够,必须对每个引用字段调用其自身的 clone() 方法(或通过其他方式如构造器、序列化等重建)。
关键点:
- 被引用的类(如
Address)也必须实现Cloneable并重写clone() - 在主类的
clone()方法中,对引用字段显式调用.clone() - 避免递归引用导致无限 clone(需加判断或使用缓存)
改进后的 Person.clone():
try {
Person cloned = (Person) super.clone();
if (this.address != null) {
cloned.address = this.address.clone(); // 深拷贝 address
}
return cloned;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
替代方案:比 clone 更可控的深拷贝方式
原生 clone() 机制存在局限性(如强制异常、破坏封装、数组与 final 字段兼容性差),生产中更推荐以下方式:
-
拷贝构造器:为类提供
Person(Person other)构造器,内部对每个字段做显式赋值或克隆 -
静态工厂方法:如
Person.copyOf(other),逻辑清晰且可灵活处理 null 或嵌套结构 -
序列化/反序列化(适用于可序列化类):借助
ObjectOutputStream写入字节数组再读回,天然实现深拷贝(但性能低、要求所有字段可序列化)
注意事项与常见陷阱
使用 clone() 时容易忽略这些细节:
-
Cloneable是标记接口,不实现会抛CloneNotSupportedException -
final字段不能在clone()中重新赋值(编译报错),需确保其值本身不可变或设计上允许共享 - 数组字段:
super.clone()对一维数组会生成新数组(浅层深拷贝),但数组元素仍是原引用;多维数组需逐层 clone - 继承链中若父类未正确实现 clone,子类 clone 可能破坏一致性


















