用序列化实现深拷贝需所有类实现Serializable并显式声明serialVersionUID;工具方法通过内存字节数组读写对象,绕过构造函数、切断引用链;但不复制static/transient字段,且存在性能、类型限制和JDK9+安全配置问题。

用序列化实现深拷贝,最直接的快捷方式就是封装一个通用工具方法,配合对象自身及所有嵌套类都实现 Serializable 接口。
核心前提:所有参与拷贝的类必须可序列化
不只是目标对象本身,它内部引用的每个类(如 Address、List<Item>、自定义集合元素等)都要声明 implements Serializable,并建议显式添加 private static final long serialVersionUID。否则运行时会抛 NotSerializableException。
一行调用的工具方法(推荐复用)
写一次,到处可用。以下方法支持任意泛型类型,异常明确,资源自动关闭(Java 7+ try-with-resources 更安全):
注意:该方法不处理 static 或 transient 字段,它们不会被复制。
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
立即学习“Java免费学习笔记(深入)”;
- 把对象写入内存字节数组,再从字节数组读出新对象
- 完全绕过构造函数,不执行任何初始化逻辑
- 天然切断所有引用链,List、Map、嵌套对象全变成新实例
简化版代码(可直接粘贴使用)
无需引入第三方库,纯 JDK 实现:
public static <T> T deepCopy(T obj) throws IOException, ClassNotFoundException {
if (obj == null) return null;
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
oos.writeObject(obj);
try (ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis)) {
return (T) ois.readObject();
}
}
}
调用示例:User copied = deepCopy(originalUser); —— 简洁、清晰、有效。
生产环境要注意的三个实际问题
- 性能敏感场景慎用:频繁调用会导致明显 GC 压力和 CPU 开销;高频拷贝建议缓存结果或改用 Kryo/Gson
-
非 Serializable 类型要排除:比如
Thread、Socket、java.awt.Image等系统类无法序列化,需提前清理或替换为可序列化包装类 -
JDK 9+ 安全限制:默认禁用反序列化,需配置
serialFilter白名单,或在启动参数中加-Djdk.serialFilter=your.package.**

















