c语言编程笔录

首页 >   > 笔记大全

笔记大全

一文带你读懂java中的对象拷贝

更新时间:2023-10-06

一、Java中的对象拷贝简介

在Java编程中,由于对象的存在,对象的拷贝是不可避免的一个操作。对象拷贝有两种方式,浅拷贝和深拷贝。浅拷贝是指拷贝对象的引用,而不是拷贝对象的内容。而深拷贝则是创建一个新的对象,同时将原对象的所有内容都拷贝到新对象中。在Java中,如果不使用拷贝的方法,而是直接将一个对象引用赋值给另一个对象引用,则这两个对象指向同一块存储空间。

class Person {
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

public class ObjectCopyDemo {
    public static void main(String[] args) {
        Person p1 = new Person(20, "John");
        Person p2 = p1;
        System.out.println(p1 == p2); // true
    }
}

二、Java中的浅拷贝

在Java中,浅拷贝是通过Object类中的clone()方法来实现的。该方法会创建一个新的对象,但是这个新对象只是将原对象的引用复制给了新对象,而没有拷贝原对象的内容。如果原对象中有引用类型的成员变量,那么拷贝后的对象和原对象会共用这些成员变量。因此,对于修改拷贝后的对象中的引用类型成员变量,原对象中的这些成员变量也会发生改变。

class Student implements Cloneable {
    private int age;
    private String name;
    private Subject subject;

    public Student(int age, String name, Subject subject) {
        this.age = age;
        this.name = name;
        this.subject = subject;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Subject getSubject() {
        return subject;
    }

    public void setSubject(Subject subject) {
        this.subject = subject;
    }

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

class Subject {
    private String name;

    public Subject(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

public class ShallowCopyDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        Subject subject = new Subject("Math");
        Student s1 = new Student(20, "John", subject);
        Student s2 = s1.clone();
        System.out.println(s1 == s2); // false
        System.out.println(s1.getSubject() == s2.getSubject()); // true,s1和s2共用同一个Subject对象
    }
}

三、Java中的深拷贝

在Java中实现对象的深拷贝有多种方法,比如使用序列化和反序列化、使用copy constructor和使用Java深拷贝库等。这里我们介绍一种使用序列化和反序列化的方式实现深拷贝。

class Address implements Serializable {
    private int number;
    private String street;

    public Address(int number, String street) {
        this.number = number;
        this.street = street;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }
}

class Student implements Serializable {
    private int age;
    private String name;
    private Address address;

    public Student(int age, String name, Address address) {
        this.age = age;
        this.name = name;
        this.address = address;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public Student deepCopy() throws IOException, ClassNotFoundException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        return (Student) ois.readObject();
    }
}

public class DeepCopyDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Address address = new Address(100, "Main St");
        Student s1 = new Student(20, "John", address);
        Student s2 = s1.deepCopy();
        System.out.println(s1 == s2); // false
        System.out.println(s1.getAddress() == s2.getAddress()); // false,s1和s2拥有各自的Address对象
    }
}

四、总结

Java中的对象拷贝是Java编程中经常会遇到的一个操作,我们需要了解浅拷贝和深拷贝的区别,并掌握如何在代码中实现深拷贝。深拷贝可以使用多种方式实现,选择不同的方式取决于具体的场景和需求。