Java深拷贝通过序列化实现,即写入字节流再读取重建对象以切断引用;要求所有相关类实现Serializable,使用ObjectOutputStream/ObjectInputStream完成,注意处理异常、transient/static字段及安全限制。

Java 中通过序列化实现对象深拷贝,核心思路是把对象“写成字节流再读回来”——这个过程天然切断所有引用关系,重建出内存地址完全独立的新对象。
前提条件:所有相关类必须可序列化
这是硬性要求,缺一不可:
- 目标类本身要声明 implements Serializable
- 它内部所有非
transient字段的类型(包括嵌套的 List、Map、自定义对象等)也都得实现Serializable - 建议显式定义
private static final long serialVersionUID,避免版本不一致导致反序列化失败 -
static和transient字段不会被序列化,副本中它们为默认值(null、0、false),如有特殊需要需手动恢复
标准实现步骤(无需第三方库)
用 ObjectOutputStream 和 ObjectInputStream 完成字节流转存与重建:
- 创建
ByteArrayOutputStream作为字节容器 - 用
ObjectOutputStream将原对象写入该容器 - 从容器中取出字节数组,用
ObjectInputStream读取并反序列化为新对象 - 务必捕获
IOException和ClassNotFoundException,二者均属检查异常
示例工具方法:
立即学习“Java免费学习笔记(深入)”;
public static <T> T deepClone(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);
@SuppressWarnings("unchecked")
T cloned = (T) ois.readObject();
ois.close();
return cloned;
}
常见问题与应对方式
实际使用中容易卡在这几个地方:
-
NotSerializableException:某个嵌套类没实现
Serializable。检查整个对象图,尤其是第三方类(如java.awt.Image、Thread)或遗漏的自定义类,可考虑封装、排除或换用反射+递归方案 - 性能偏低:序列化涉及 I/O 和反射,不适合高频调用。小对象或低频场景可用;高频时建议结合对象池或缓存已拷贝结果
-
构造函数不执行:反序列化不走任何构造器。若初始化逻辑依赖构造函数(比如注册监听、分配资源),需在类中重写
readObject()方法补充 -
安全性限制:JDK 9+ 默认禁用反序列化,生产环境必须配置
serialFilter或白名单策略,并严格校验输入来源
和原型模式结合更自然
原型模式只要求“用已有对象创建新对象”,并不限定用 clone()。你可以让具体原型类实现 Cloneable,但在重写的 clone() 方法里直接调用上面的 deepClone() 工具方法——既满足接口契约,又获得真正的深拷贝保障,还规避了手动递归克隆易漏字段的风险。


















