java中深拷贝的方式有哪些

发布时间:2022-08-27 09:22:30 作者:iii
来源:亿速云 阅读:112

Java中深拷贝的方式有哪些

在Java编程中,对象的拷贝是一个常见的操作。拷贝可以分为浅拷贝和深拷贝两种。浅拷贝只复制对象的引用,而不复制对象本身,这意味着拷贝后的对象和原对象共享同一块内存。而深拷贝则是创建一个新的对象,并且复制原对象的所有内容,包括其引用的对象。深拷贝后的对象和原对象是完全独立的,修改其中一个不会影响另一个。

本文将详细介绍Java中实现深拷贝的几种方式,并通过代码示例进行说明。

1. 使用clone()方法实现深拷贝

Java中的clone()方法是一个用于对象拷贝的常用方法。要实现深拷贝,需要在clone()方法中递归地调用所有引用类型字段的clone()方法。

1.1 实现Cloneable接口

首先,需要让类实现Cloneable接口,并重写clone()方法。

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

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Person cloned = (Person) super.clone();
        cloned.address = (Address) address.clone();
        return cloned;
    }

    // Getters and setters
}

class Address implements Cloneable {
    private String city;

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

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

    // Getters and setters
}

1.2 使用clone()方法进行深拷贝

public class DeepCopyExample {
    public static void main(String[] args) {
        try {
            Address address = new Address("New York");
            Person person1 = new Person("John", address);
            Person person2 = (Person) person1.clone();

            System.out.println(person1.getAddress().getCity()); // Output: New York
            System.out.println(person2.getAddress().getCity()); // Output: New York

            person2.getAddress().setCity("Los Angeles");

            System.out.println(person1.getAddress().getCity()); // Output: New York
            System.out.println(person2.getAddress().getCity()); // Output: Los Angeles
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

1.3 注意事项

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

Java中的序列化机制可以将对象转换为字节流,然后再将字节流反序列化为对象。通过序列化和反序列化,可以实现深拷贝。

2.1 实现Serializable接口

首先,需要让类实现Serializable接口。

import java.io.Serializable;

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

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

    // Getters and setters
}

class Address implements Serializable {
    private String city;

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

    // Getters and setters
}

2.2 使用序列化进行深拷贝

import java.io.*;

public class DeepCopyExample {
    public static void main(String[] args) {
        try {
            Address address = new Address("New York");
            Person person1 = new Person("John", address);

            // Serialize
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(person1);
            oos.flush();

            // Deserialize
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            Person person2 = (Person) ois.readObject();

            System.out.println(person1.getAddress().getCity()); // Output: New York
            System.out.println(person2.getAddress().getCity()); // Output: New York

            person2.getAddress().setCity("Los Angeles");

            System.out.println(person1.getAddress().getCity()); // Output: New York
            System.out.println(person2.getAddress().getCity()); // Output: Los Angeles
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

2.3 注意事项

3. 使用第三方库实现深拷贝

除了手动实现深拷贝和使用序列化外,还可以借助一些第三方库来实现深拷贝。常见的第三方库包括Apache Commons Lang和Kryo等。

3.1 使用Apache Commons Lang实现深拷贝

Apache Commons Lang库提供了一个SerializationUtils.clone()方法,可以方便地实现深拷贝。

3.1.1 添加依赖

首先,需要在项目中添加Apache Commons Lang的依赖。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

3.1.2 使用SerializationUtils.clone()方法

import org.apache.commons.lang3.SerializationUtils;

public class DeepCopyExample {
    public static void main(String[] args) {
        Address address = new Address("New York");
        Person person1 = new Person("John", address);
        Person person2 = SerializationUtils.clone(person1);

        System.out.println(person1.getAddress().getCity()); // Output: New York
        System.out.println(person2.getAddress().getCity()); // Output: New York

        person2.getAddress().setCity("Los Angeles");

        System.out.println(person1.getAddress().getCity()); // Output: New York
        System.out.println(person2.getAddress().getCity()); // Output: Los Angeles
    }
}

3.2 使用Kryo实现深拷贝

Kryo是一个高效的Java序列化库,支持深拷贝。

3.2.1 添加依赖

首先,需要在项目中添加Kryo的依赖。

<dependency>
    <groupId>com.esotericsoftware</groupId>
    <artifactId>kryo</artifactId>
    <version>5.3.0</version>
</dependency>

3.2.2 使用Kryo进行深拷贝

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

public class DeepCopyExample {
    public static void main(String[] args) {
        Kryo kryo = new Kryo();
        kryo.register(Person.class);
        kryo.register(Address.class);

        Address address = new Address("New York");
        Person person1 = new Person("John", address);

        // Serialize
        Output output = new Output(1024, -1);
        kryo.writeObject(output, person1);
        byte[] bytes = output.toBytes();

        // Deserialize
        Input input = new Input(bytes);
        Person person2 = kryo.readObject(input, Person.class);

        System.out.println(person1.getAddress().getCity()); // Output: New York
        System.out.println(person2.getAddress().getCity()); // Output: New York

        person2.getAddress().setCity("Los Angeles");

        System.out.println(person1.getAddress().getCity()); // Output: New York
        System.out.println(person2.getAddress().getCity()); // Output: Los Angeles
    }
}

3.3 注意事项

4. 手动实现深拷贝

在某些情况下,可能需要手动实现深拷贝,特别是当对象结构复杂或需要特殊处理时。

4.1 手动复制所有字段

手动实现深拷贝的关键是递归地复制所有字段,包括引用类型的字段。

class Person {
    private String name;
    private Address address;

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

    public Person deepCopy() {
        Address copiedAddress = new Address(this.address.getCity());
        return new Person(this.name, copiedAddress);
    }

    // Getters and setters
}

class Address {
    private String city;

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

    // Getters and setters
}

4.2 使用手动深拷贝

public class DeepCopyExample {
    public static void main(String[] args) {
        Address address = new Address("New York");
        Person person1 = new Person("John", address);
        Person person2 = person1.deepCopy();

        System.out.println(person1.getAddress().getCity()); // Output: New York
        System.out.println(person2.getAddress().getCity()); // Output: New York

        person2.getAddress().setCity("Los Angeles");

        System.out.println(person1.getAddress().getCity()); // Output: New York
        System.out.println(person2.getAddress().getCity()); // Output: Los Angeles
    }
}

4.3 注意事项

5. 使用ObjectMapper实现深拷贝

Jackson库中的ObjectMapper类可以用于将对象序列化为JSON字符串,然后再将JSON字符串反序列化为对象,从而实现深拷贝。

5.1 添加依赖

首先,需要在项目中添加Jackson的依赖。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

5.2 使用ObjectMapper进行深拷贝

import com.fasterxml.jackson.databind.ObjectMapper;

public class DeepCopyExample {
    public static void main(String[] args) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();

            Address address = new Address("New York");
            Person person1 = new Person("John", address);

            // Serialize to JSON
            String json = objectMapper.writeValueAsString(person1);

            // Deserialize from JSON
            Person person2 = objectMapper.readValue(json, Person.class);

            System.out.println(person1.getAddress().getCity()); // Output: New York
            System.out.println(person2.getAddress().getCity()); // Output: New York

            person2.getAddress().setCity("Los Angeles");

            System.out.println(person1.getAddress().getCity()); // Output: New York
            System.out.println(person2.getAddress().getCity()); // Output: Los Angeles
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5.3 注意事项

6. 总结

在Java中实现深拷贝有多种方式,每种方式都有其优缺点。选择哪种方式取决于具体的应用场景和需求。

在实际开发中,应根据具体需求选择最合适的深拷贝方式。

推荐阅读:
  1. 浅谈Java中实现深拷贝的两种方式—clone() & Serialized
  2. java中String的赋值方式有哪些

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:Mybatis中怎么使用in()查询

下一篇:Android中的监听和按键怎么处理

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》