Java对象克隆默认为浅拷贝,深拷贝需手动递归、序列化或第三方工具实现;浅拷贝仅复制引用地址,深拷贝需确保嵌套对象完全独立,且Cloneable仅为标记接口,super.clone()不执行构造逻辑。

Java对象克隆机制本身不直接提供深拷贝能力,默认只支持浅拷贝。要实现真正独立的副本,必须明确区分两种拷贝行为,并按需扩展。
浅拷贝:只需满足两个前提
浅拷贝复制对象自身及基本类型字段,对引用类型仅复制地址——新旧对象共享嵌套对象。实现它需要:
- 类声明实现
Cloneable接口(纯标记,无方法) - 重写
clone()方法,访问权限改为public,并调用super.clone() - 处理
CloneNotSupportedException异常(通常在方法签名中抛出)
例如:Person 类含 String name、int age 和 Address addr 字段。调用 p2 = p1.clone() 后,p2.name 和 p2.age 修改不影响 p1;但 p2.addr.city = "上海" 会同步反映在 p1.addr.city 上。
深拷贝:三种主流实现方式
深拷贝要求所有嵌套对象也生成新实例,确保完全隔离。常用路径有:
立即学习“Java免费学习笔记(深入)”;
-
手动递归克隆:在重写的
clone()中,对每个可变引用字段调用其clone()方法(该字段所属类也需实现Cloneable并提供public clone()) -
序列化/反序列化:将对象写入字节流再读出,天然实现完整复制。要求所有字段所属类实现
Serializable,且注意transient字段会被跳过 -
第三方工具辅助:如 Apache Commons Lang 的
SerializationUtils.clone(),本质是封装了序列化逻辑,一行代码即可,但依赖可序列化
注意:若使用构造器或 builder 模式新建对象(如 new Person(p1.getName(), p1.getAge(), new Address(p1.getAddress().getCity()))),虽非 clone() 体系,但语义清晰、可控性强,实际项目中更推荐。
常见陷阱与关键细节
克隆不是“开箱即用”的安全操作,容易踩坑:
-
Cloneable不是功能接口,仅起 JVM 标记作用;没实现它就调用clone()必抛异常 -
super.clone()不走构造函数,字段初始化逻辑不会执行 - 父类未实现
Cloneable,子类即使实现了,调用super.clone()仍会失败 - 含不可序列化资源(如
ThreadLocal、Socket)的对象,不能用序列化方式做深拷贝
不复杂但容易忽略


















