java 对象序列化中实现深拷贝,最直接且通用的做法是利用 objectoutputstream 和 objectinputstream 将对象写入内存字节流后再读回。调用 writeobject() 进行序列化,随后调用 readobject() 反序列化,返回的对象在堆内存中具有全新的地址,其内部引用的可变对象也会被递归地创建新实例,从而实现彻底的深拷贝。需要注意的是,参与序列化的类必须实现 serializable 接口,且所有成员变量类型也必须是可序列化的,否则会在运行时抛出异常。

Serializable 接口对深拷贝的影响是什么
要实现基于序列化的深拷贝,目标类及其所有引用类型的成员变量都必须实现 Serializable 接口。这是一个标记型接口,不包含任何方法,它的作用是告诉 JVM 该类的实例可以被转换为字节流。如果类中的某个字段是自定义对象但未实现此接口,或者包含如 Thread、FileOutputStream 等不可序列化的系统资源,序列化过程会失败并抛出 NotSerializableException。因此,确保整个对象图的每个节点都具备可序列化能力是实现该方案的前提条件。

import java.io.*;
public class DeepCopyExample {
public static void main(String[] args) throws Exception {
// 定义一个需要深拷贝的类
Person person = new Person("Alice", new Address("Beijing"));
// 执行深拷贝
Person clonedPerson = deepCopy(person);
// 验证结果
System.out.println("Original: " + person.getAddress().getCity());
System.out.println("Cloned: " + clonedPerson.getAddress().getCity());
System.out.println("Same ref? " + (person == clonedPerson));
System.out.println("Addr Same? " + (person.getAddress() == clonedPerson.getAddress()));
}
@SuppressWarnings("unchecked")
public static <T> T deepCopy(T obj) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
T result = (T) ois.readObject();
ois.close();
return result;
}
}
class Person implements Serializable {
private String name;
private Address address;
public Person(String name, Address address) { this.name = name; this.address = address; }
public Address getAddress() { return address; }
}
class Address implements Serializable {
private String city;
public Address(String city) { this.city = city; }
public String getCity() { return city; }
}
序列化深拷贝与浅拷贝的行为差异在哪里
序列化深拷贝与浅拷贝的核心差异在于对引用类型字段的处理深度。浅拷贝(如重写 clone() 但不递归克隆)只会复制基本数据类型和对象引用本身,导致原对象和拷贝对象共享同一个内部可变对象的内存地址。而序列化机制会将整个对象图扁平化为字节流,反序列化时重新构建完整的对象树,这意味着不仅顶层对象是新实例,其内部引用的所有子对象也是新创建的独立实例。这种差异使得序列化深拷贝在处理复杂嵌套结构时更加安全可靠,避免了修改拷贝对象内部状态时意外影响原对象的风险。
立即学习“Java免费学习笔记(深入)”;

当对象图中存在循环引用时深拷贝能成功吗
当对象图中存在循环引用时,基于标准 Java 序列化的深拷贝依然可以成功执行。JVM 的序列化机制内置了对象追踪表(Object Table),在序列化过程中会记录已经写入过的对象引用。当遇到循环引用或同一对象的多次引用时,序列化器不会无限递归,而是写入一个指向之前已序列化对象的句柄(Handle)。反序列化时,读取器会根据句柄恢复相同的对象引用关系。因此,即使 Person 对象中有一个字段指向自身,或者两个对象互相引用,序列化深拷贝也能正确重建这种复杂的拓扑结构,保证拷贝后的对象图结构与原对象完全一致,包括所有的循环依赖关系。


















