java中object.clone()默认是浅拷贝:基本类型字段复制值,引用类型字段仅复制地址,新旧对象共享同一堆内存中的可变对象实例。

Java 中 Object.clone() 方法默认实现的是浅拷贝,但要正确使用它,必须满足两个前提:类需实现 Cloneable 接口,且需重写 clone() 方法并声明为 public。
为什么 clone() 默认是浅拷贝
Object 的原生 clone() 方法会创建一个新对象,并将原对象的字段值(基本类型直接复制值,引用类型复制地址)逐个复制过去。这意味着如果对象包含引用类型字段(如数组、集合、自定义对象等),新旧对象仍共享同一份堆内存中的引用对象。
- 基本类型字段(如
int、boolean)——复制值,互不影响 - 引用类型字段(如
StringBuffer、List、自定义对象)——复制的是引用地址,修改其中一个会影响另一个
如何正确调用 clone() 实现浅拷贝
直接调用 super.clone() 即可获得浅拷贝结果,但必须显式处理访问权限和异常:
- 实现
Cloneable接口(仅作标记,不提供方法) - 重写
clone()方法,改为public访问级别(Object 中是protected) - 捕获或声明抛出
CloneNotSupportedException
示例代码:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
public class Person implements Cloneable {<br> private String name;<br> private int age;<br> private Address address; // 引用类型<br><br> @Override<br> public Person clone() {<br> try {<br> return (Person) super.clone();<br> } catch (CloneNotSupportedException e) {<br> throw new RuntimeException(e);<br> }<br> }<br>}
此时 person.clone() 得到的对象与原对象字段值相同,但 address 字段指向同一个 Address 实例。
浅拷贝 vs 深拷贝的关键区别
浅拷贝只复制一层引用,深拷贝需递归克隆所有嵌套对象。若需要深拷贝,不能依赖 Object.clone() 默认行为,而要手动处理引用字段:
- 对每个引用字段调用其自身的
clone()(要求该类也支持克隆) - 或用序列化、JSON 工具、构造器等方式重建对象图
- 例如:
this.address = this.address.clone();(前提是Address也实现了Cloneable)
常见陷阱与注意事项
忽略以下细节容易导致运行时异常或逻辑错误:
- 未实现
Cloneable接口就调用clone()→ 抛CloneNotSupportedException - 重写后仍为
protected→ 外部无法调用 - final 字段无法被 clone 修改(编译期常量除外),可能引发意外状态
- 某些 JDK 类(如
String、不可变集合)虽是引用类型,但因不可变性,浅拷贝实际表现安全
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










