Java对象深拷贝有序列化和递归clone两种方式:前者自动、通用,要求所有类实现Serializable并声明serialVersionUID;后者可控但需手动维护每个引用字段的克隆逻辑,且易因遗漏导致浅拷贝。

Java 中对象深拷贝通过序列化实现,本质是把对象“转成字节流”再重建,天然断开所有引用关系;递归实现则依赖手动克隆每一层引用字段,需逐级调用 clone() 方法。两者都能达成完全独立副本,但适用场景和约束不同。
序列化方式:自动、通用、无需手动处理嵌套
只要目标类及其所有内部引用类型(如 Address、List<User>、Map<String, Department>)都实现 Serializable 接口,并显式声明 serialVersionUID,就能借助 Java 原生序列化机制完成深拷贝:
- 使用
ObjectOutputStream将对象写入ByteArrayOutputStream - 再用
ObjectInputStream从ByteArrayInputStream读出新对象 - 过程中所有嵌套对象都会被重新实例化,内存地址完全不同
- 自动绕过循环引用(部分 JDK 版本支持)、集合类型、多层嵌套等复杂结构
- 不依赖
Cloneable,也不用重写clone()
递归 clone 方式:可控性强,但需人工维护
该方式基于 Cloneable 接口和重写的 clone() 方法,对每个引用字段显式调用其 clone():
- 基础类(如
Address)必须实现Cloneable并重写clone()返回自身副本 - 外层类(如
Person)在clone()中先调用super.clone()得到浅拷贝,再对每个引用字段(如address、work)单独克隆赋值 - 集合类需额外处理:不能直接调用
list.clone()(那是浅拷贝),要遍历并克隆每个元素 - 一旦新增引用字段或嵌套层级,必须同步更新
clone()方法,否则出现浅拷贝漏洞
关键注意事项
两种方式都有一些共性限制和易错点:
立即学习“Java免费学习笔记(深入)”;
-
transient字段不会被序列化,也不会出现在递归 clone 中,需额外手动复制 - 静态字段不属于对象实例,无论哪种方式都不会被拷贝
- 不可序列化的类(如某些第三方类、含非序列化资源的类)会导致
NotSerializableException - 递归 clone 要求所有引用类型都支持克隆,否则编译或运行时报错
- 序列化有性能开销,高频拷贝场景建议评估是否必要
推荐组合策略
实际项目中可结合两者优势:
- 将序列化封装为通用工具方法,供任意可序列化对象调用
- 在原型模式中,让具体原型类的
clone()内部调用该序列化工具,既满足接口规范,又避免手写递归缺陷 - 对性能敏感且结构稳定的对象,可保留递归 clone 并配合单元测试验证每层拷贝正确性


















