序列化+反序列化实现深拷贝的核心是将对象转为字节流再读回,要求所有相关类实现serializable接口并建议显式声明serialversionuid;静态和transient字段不被复制;构造函数不执行,性能较低且受安全策略限制。

用序列化+反序列化做深拷贝,核心就一条:把对象“写成字节流再读回来”,新对象和原对象内存地址不同、引用链彻底断开。
前提条件:所有相关类必须可序列化
目标对象及其内部每个字段(包括嵌套的 List、Map、自定义类等)都得实现 Serializable 接口。缺一个就会抛 NotSerializableException。
- 每个类加上
implements Serializable - 建议显式声明
private static final long serialVersionUID = 1L;,避免因类结构微调导致反序列化失败 - 静态字段、
transient字段不会被复制,副本中为默认值(如 null、0)
基础工具方法(一行调用即可)
封装一个通用方法,支持任意可序列化类型:
public static <t> T deepCopy(T obj) throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (T) ois.readObject();
}</t>
使用时直接传入对象,返回全新实例:
Person original = new Person("张三", new Address("北京"));
Person copy = deepCopy(original); // copy 和 original 完全独立
注意这些实际限制
它不是万能银弹,几个关键点要心里有数:
- 构造函数不执行:反序列化绕过所有构造器,如果初始化逻辑写在构造里(比如注册监听、加载资源),副本里不会触发
- 性能不高:涉及 IO 流、反射、字节操作,高频或大数据量场景慎用;小对象或低频复制很稳妥
- 安全策略影响:JDK 9+ 默认禁用反序列化,需配置
serialFilter白名单,否则抛 InvalidClassException - 不支持非 Serializable 类型:像
Thread、Socket、java.awt.Image等系统类无法直接拷贝
替代思路:JSON 方案(不改源码也能用)
如果没法让类实现 Serializable(比如第三方类),可用 Gson 或 Jackson:
Gson gson = new Gson(); String json = gson.toJson(obj); // 序列化为字符串 T copy = gson.fromJson(json, obj.getClass()); // 反序列化为新对象
优点是无需修改类定义;缺点是丢失 transient、静态字段、方法,且不支持循环引用和泛型擦除后的精确类型还原(集合需配合 TypeToken)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











