本文目录导读:

在Java中实现深度拷贝(Deep Copy)主要有以下几种方式,我将按照推荐程度和使用场景分别介绍。
序列化方式(最常用)
通过Java序列化机制实现,对象及其所有引用对象都会被复制。
import java.io.*;
public class DeepCopyBySerialization {
// 方法实现
@SuppressWarnings("unchecked")
public static <T extends Serializable> T deepCopy(T obj) {
try {
// 序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
oos.flush();
// 反序列化
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (T) ois.readObject();
} catch (Exception e) {
throw new RuntimeException("Deep copy failed", e);
}
}
// 测试示例
public static void main(String[] args) {
Address address = new Address("Beijing", "China");
Person original = new Person("张三", 25, address);
Person copied = deepCopy(original);
// 验证深度拷贝 - 修改地址不影响原对象
copied.getAddress().setCity("Shanghai");
System.out.println("Original: " + original); // Beijing
System.out.println("Copied: " + copied); // Shanghai
}
}
// 实体类必须实现Serializable接口
class Person implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private int age;
private Address address;
// getters/setters 省略
// 构造方法、toString方法
}
class Address implements Serializable {
private static final long serialVersionUID = 1L;
private String city;
private String country;
// getters/setters 省略
// 构造方法、toString方法
}
优点:实现简单,自动处理所有引用 缺点:所有类必须实现Serializable,性能相对较差
手动实现Cloneable接口
通过重写clone()方法,手动复制每个属性。
public class DeepCopyByCloneable implements Cloneable {
// 方式一:手动实现clone
static class Person implements Cloneable {
private String name;
private int age;
private Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
// 手动深度拷贝引用类型
cloned.address = (Address) address.clone();
return cloned;
}
// getters/setters
}
static class Address implements Cloneable {
private String city;
private String country;
public Address(String city, String country) {
this.city = city;
this.country = country;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
// getters/setters
}
public static void main(String[] args) throws CloneNotSupportedException {
Address address = new Address("Beijing", "China");
Person original = new Person("张三", 25, address);
Person copied = (Person) original.clone();
// 验证
copied.getAddress().setCity("Shanghai");
System.out.println("Original: " + original); // Beijing
System.out.println("Copied: " + copied); // Shanghai
}
}
优点:性能最好,灵活控制复制逻辑 缺点:需要为每个类实现clone(),开发工作量大
使用JSON序列化
利用JSON库(如Jackson、Gson)实现深度拷贝。
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanUtils;
public class DeepCopyByJSON {
// 使用Jackson
public static <T> T deepCopyByJackson(T obj, Class<T> clazz) {
try {
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(obj);
return mapper.readValue(json, clazz);
} catch (Exception e) {
throw new RuntimeException("JSON deep copy failed", e);
}
}
// 使用Gson
public static <T> T deepCopyByGson(T obj, Class<T> clazz) {
com.google.gson.Gson gson = new com.google.gson.Gson();
String json = gson.toJson(obj);
return gson.fromJson(json, clazz);
}
// 测试
public static void main(String[] args) {
Person person = new Person("李四", 30, new Address("Beijing", "China"));
// Jackson方式
Person jacksonCopy = deepCopyByJackson(person, Person.class);
// Gson方式
Person gsonCopy = deepCopyByGson(person, Person.class);
}
}
优点:不需要实现Serializable,对第三方类也有效 缺点:需要外部依赖,循环引用可能导致问题
复制构造函数方式
通过专门的复制构造函数实现。
public class DeepCopyByConstructor {
static class Person {
private String name;
private int age;
private Address address;
// 普通构造函数
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
// 复制构造函数
public Person(Person other) {
this.name = other.name;
this.age = other.age;
// 深度拷贝引用类型
this.address = new Address(other.address);
}
}
static class Address {
private String city;
private String country;
public Address(String city, String country) {
this.city = city;
this.country = country;
}
// 复制构造函数
public Address(Address other) {
this.city = other.city;
this.country = other.country;
}
}
public static void main(String[] args) {
Address address = new Address("Beijing", "China");
Person original = new Person("张三", 25, address);
Person copied = new Person(original);
}
}
使用第三方库
// 使用Apache Commons Lang3
import org.apache.commons.lang3.SerializationUtils;
public class DeepCopyByCommons3 {
public static <T extends Serializable> T deepCopy(T obj) {
return SerializationUtils.clone(obj);
}
}
// 使用Spring BeanUtils(注意:只能深度拷贝第一层)
import org.springframework.beans.BeanUtils;
public class DeepCopyBySpring {
public static <T> T shallowCopy(T source, T target) {
BeanUtils.copyProperties(source, target);
return target;
}
}
推荐使用场景总结
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 简单对象图 | 序列化方式 | 实现简单,一劳永逸 |
| 性能要求高 | 手动Cloneable | 避免反射和序列化开销 |
| 第三方对象 | JSON序列化 | 无需修改原类 |
| 对象结构固定 | 复制构造函数 | 类型安全,可控性强 |
注意事项
- 循环引用:序列化和JSON方式可能无法处理循环引用
- 单例模式:深度拷贝可能会破坏单例
- 不可变对象:不需要深度拷贝,直接引用即可
- 性能选择:如果频繁使用,建议使用手动Cloneable方式
选择哪种方式主要取决于你的具体需求、性能要求和开发成本,对于大多数业务场景,序列化方式是最简单实用的选择。