java中序列化实现深拷贝的核心是将对象写为字节流再读取为新实例,从而切断引用并递归重建对象图;要求所有嵌套类实现serializable接口且显式声明serialversionuid, transient/static字段不参与复制,全程内存操作,但存在性能差、不可序列化类型报错、构造逻辑丢失等限制。

Java 中用序列化配合深拷贝复制复杂嵌套对象,核心是“把对象写成字节流,再从字节流里读出一个全新实例”——这个过程天然切断所有引用,递归重建整个对象图。
前提条件:所有类必须可序列化
每个参与嵌套的类(包括字段类型、集合元素类型)都得实现 Serializable 接口,并建议显式声明 serialVersionUID。比如:
-
Person类实现Serializable - 它持有的
Address字段类型也得实现Serializable - List、Map 等容器本身可序列化,但其中存的对象也得可序列化
- 含
transient或static字段的类,这些字段不会被复制,需额外处理
标准实现:内存中完成,不落磁盘
不用文件 IO,全程走 ByteArrayInputStream 和 ByteArrayOutputStream,避免 I/O 开销和异常干扰:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 用
ByteArrayOutputStream包装ObjectOutputStream - 调用
writeObject(this)把当前对象写进去 - 取
toByteArray()得到字节数组 - 用该数组构造
ByteArrayInputStream,再包装成ObjectInputStream - 调用
readObject()并强转为目标类型 - 务必用 try-with-resources 自动关闭流,防止资源泄漏
关键限制与避坑点
这不是万能银弹,要注意几个硬约束:
- 不可序列化的资源(如
Thread、Socket、FileInputStream)会直接抛NotSerializableException -
java.time.*类虽可序列化,但某些自定义时区或反序列化钩子没写好,可能出错 - 构造函数不会执行,初始化逻辑(如 lazy 初始化、注册监听器)在副本中丢失
- 性能比手动 clone 或 Jackson JSON 方式慢一个数量级,高频调用场景慎用
更稳妥的替代选择
如果只是想快速可靠地深拷贝,推荐优先考虑这些方式:
- 用
SerializationUtils.clone(obj)(Apache Commons Lang),已封装异常和流管理 - POJO 结构清晰时,用 Jackson 的
ObjectMapper.readValue(json, type),不依赖Serializable - 对性能敏感或结构固定,为关键类显式实现
clone(),逐字段控制复制逻辑 - 长期维护项目,考虑改用不可变对象(Immutable),从源头消除深拷贝需求
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










