Java案例怎么实现深度拷贝?

wen java案例 11

本文目录导读:

Java案例怎么实现深度拷贝?

  1. 序列化方式(最常用)
  2. 手动实现Cloneable接口
  3. 使用JSON序列化
  4. 复制构造函数方式
  5. 使用第三方库
  6. 推荐使用场景总结
  7. 注意事项

在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序列化 无需修改原类
对象结构固定 复制构造函数 类型安全,可控性强

注意事项

  1. 循环引用:序列化和JSON方式可能无法处理循环引用
  2. 单例模式:深度拷贝可能会破坏单例
  3. 不可变对象:不需要深度拷贝,直接引用即可
  4. 性能选择:如果频繁使用,建议使用手动Cloneable方式

选择哪种方式主要取决于你的具体需求、性能要求和开发成本,对于大多数业务场景,序列化方式是最简单实用的选择。

抱歉,评论功能暂时关闭!