Java实现深拷贝的方式

1. 实现 Cloneable 接口并重写 clone() 方法

在 Java 中,实现深拷贝的一种方式是实现 Cloneable 接口并重写 clone() 方法。深拷贝是指在拷贝对象时,不仅拷贝对象本身,还要递归地拷贝其所有引用对象,以确保原始对象和拷贝对象的属性引用不同的对象实例。

public class jvmtestMain {
    public static void main(String[] args) throws  CloneNotSupportedException {
        Address a=new Address("北京");
        Address b= (Address) a.clone();
        System.out.println(b.getCity());
        System.out.println("a,b是否指向同一个对象:"+a.equals(b));
    }
}
class Address implements Cloneable {
    private String city;

    public Address(String city) {
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

在这里插入图片描述

2. 使用序列化和反序列化实现深拷贝

序列化是将对象转换为字节流的过程,以便可以将其保存到磁盘文件、通过网络传输或在内存中保存。序列化将对象的状态以二进制形式编码,以便稍后可以重新创建对象,这个过程称为反序列化。序列化在 Java 中有许多应用,其中之一是实现深拷贝。

public class jvmtestMain {
    public static <T> T deepClone(T obj) throws IOException, ClassNotFoundException {
        //序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream out = new ObjectOutputStream(bos);
        out.writeObject(obj);
        out.close();

        //反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream in = new ObjectInputStream(bis);
        T clone = (T) in.readObject();
        in.close();

        return clone;
    }

    public static void main(String[] args) {
        Address originalAddress = new Address("New York");
        Person originalPerson = new Person("Alice", originalAddress);

        try {
            // Perform deep clone using serialization
            Person clonedPerson = deepClone(originalPerson);

            // Modify the cloned object
            clonedPerson.setName("Bob");
            clonedPerson.getAddress().setCity("Los Angeles");

            System.out.println("Original Person: " + originalPerson.getName() + ", " + originalPerson.getAddress().getCity());
            System.out.println("Cloned Person: " + clonedPerson.getName() + ", " + clonedPerson.getAddress().getCity());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
class Address implements Serializable {
    private String city;

    public Address(String city) {
        this.city = city;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city){
        this.city=city;
    }
}

class Person implements Serializable {
    private String name;
    private Address address;

    public Person(String name, Address address) {
        this.name = name;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name){
        this.name=name;
    }

    public Address getAddress() {
        return address;
    }
}

在这里插入图片描述

3. 第三方工具

除此之外,还有一些第三方工具可以实现对象克隆,例如 Apache Commons BeanUtils 库的 BeanUtils.cloneBean() 方法和 Spring Framework 的 ObjectUtils.clone() 方法。

(1) Apache Commons BeanUtils 库

使用 BeanUtils.cloneBean() 方法可以对一个对象进行浅拷贝。

Person person1 = new Person("Alice", 20);
Person person2 = BeanUtils.cloneBean(person1);

(2) Apache Commons Lang 库

Apache Commons Lang 库提供了 SerializationUtils.clone() 方法,可以对对象进行深拷贝。

Person person1 = new Person("Alice", 20);
Person person2 = SerializationUtils.clone(person1);

(3) Spring Framework

使用 Spring Framework 的 ObjectUtils.clone() 方法可以对一个对象进行深拷贝。

Person person1 = new Person("Alice", 20);
Person person2 = (Person) ObjectUtils.clone(person1);

(4) Kryo 序列化库

Kryo 是一种快速、高效的 Java 序列化库,可以用于实现对象的深拷贝。使用 Kryo 序列化库实现对象的克隆需要先定义一个 Kryo 对象,然后对需要克隆的对象进行序列化和反序列化。例如:

Kryo kryo = new Kryo();
kryo.setRegistrationRequired(false);

Person person1 = new Person("Alice", 20);
Person person2 = kryo.copy(person1);

(5) FST 序列化库

FST 是一种基于字节码的 Java 序列化库,可以用于实现对象的深拷贝。使用 FST 序列化库实现对象的克隆需要先定义一个 FSTConfiguration 对象,然后对需要克隆的对象进行序列化和反序列化。

FSTConfiguration configuration = FSTConfiguration.createDefaultConfiguration();

Person person1 = new Person("Alice", 20);
Person person2 = (Person) configuration.asObject(configuration.asByteArray(person1));

需要注意的是,如果要克隆的对象中包含了集合、数组、Map 或其他引用类型的属性,需要保证这些属性的类型也是可克隆的或可序列化的,否则可能会导致克隆出来的对象不完整或者抛出异常。此外,在实现克隆时,还需要考虑线程安全等问题。使用第三方库实现对象克隆可能会带来一定的性能开销和额外的依赖,因此需要权衡利弊,选择适合自己的实现方式。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java实现深拷贝有几种方式,下面是其中两种常用的方式: 1. 使用Cloneable接口和clone()方法: Java中的Object类提供了一个clone()方法,通过实现Cloneable接口并重写clone()方法,可以实现对象的深拷贝。具体步骤如下: - 在需要进行深拷贝的类中实现Cloneable接口。 - 重写clone()方法,在方法内部使用super.clone()进行浅拷贝,然后对引用类型的属性进行深拷贝。 - 在使用时,通过调用clone()方法创建一个新的对象。 以下是一个示例代码: ```java public class MyClass implements Cloneable { private int number; private MyObject myObject; public MyClass(int number, MyObject myObject) { this.number = number; this.myObject = myObject; } @Override protected Object clone() throws CloneNotSupportedException { MyClass cloned = (MyClass) super.clone(); cloned.myObject = (MyObject) myObject.clone(); return cloned; } } public class MyObject implements Cloneable { // ... @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } } ``` 2. 使用序列化和反序列化: 另一种实现深拷贝方式是通过将对象进行序列化和反序列化来创建一个新的对象。具体步骤如下: - 在需要进行深拷贝的类中实现Serializable接口。 - 将对象写入到一个字节流中,然后再从字节流中读取出来,即可得到一个新的对象。 以下是一个示例代码: ```java import java.io.*; public class MyClass implements Serializable { private int number; private MyObject myObject; public MyClass(int number, MyObject myObject) { this.number = number; this.myObject = myObject; } public MyClass deepCopy() throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (MyClass) ois.readObject(); } } public class MyObject implements Serializable { // ... } ``` 这两种方式都可以实现深拷贝,具体选择哪种方式取决于具体的需求和场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值