欢迎访问宙启技术站
智能推送

java中深复制与浅复制的区别是什么

发布时间:2023-05-14 15:26:30

Java中的深复制(Deep Copy)和浅复制(Shallow Copy)是非常重要的概念,其中深复制是复制一个对象的所有内容,包括对象的引用类型,而浅复制仅仅是复制对象本身,不涉及到对象的引用类型。在这篇文章中,我将详细讨论Java中深复制与浅复制的区别。

深复制(Deep Copy)

在Java中,如果我们想要复制一个对象的所有内容,包括对象内容和引用类型,那么就需要使用深复制。在深复制中,对象及其所有引用类型都会被复制到一个新的对象中,因此,新的对象与原始对象是完全独立的。这意味着,如果我们在新对象中修改一个引用类型的值,那么原始对象不会受到任何影响。

让我们考虑以下示例代码:

public class Student implements Cloneable {

    private String name;

    private int age;

    private Department department;

    public Student(String name, int age, Department department) {

        this.name = name;

        this.age = age;

        this.department = department;

    }

    public void setDepartment(Department department) {

        this.department = department;

    }

    public String getName() {

        return name;

    }

    public int getAge() {

        return age;

    }

    public Department getDepartment() {

        return department;

    }

    @Override

    public Object clone() throws CloneNotSupportedException {

        Student student = (Student) super.clone();

        student.department = (Department) department.clone();

        return student;

    }

}

public class Department implements Cloneable {

    private String name;

    public Department(String name) {

        this.name = name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getName() {

        return name;

    }

    @Override

    public Object clone() throws CloneNotSupportedException {

        return super.clone();

    }

}

在上面的示例中,我们有一个学生类,其中包括学生的名字、年龄和一个Department对象。我们还有一个Department类,其中包括名称。

要将Student类进行深复制,我们需要使其实现Cloneable接口并重写clone方法。在clone方法中,我们创建一个Student对象,并将其字段复制到新对象中。由于Department类中也有一个引用类型,我们需要在Student类的clone方法中调用Department类的clone方法来完成深复制。在Department类的clone方法中,我们只需使用Object类的clone方法,因为它只包含基本类型。

让我们测试一下:

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {

        Department department = new Department("Software Engineering");

        Student student1 = new Student("Alice", 20, department);

        Student student2 = (Student) student1.clone();

        System.out.println("student1: " + student1.getName() + " " + student1.getAge() + " " + student1.getDepartment().getName());

        System.out.println("student2: " + student2.getName() + " " + student2.getAge() + " " + student2.getDepartment().getName());

        student2.getDepartment().setName("Computer Science");

        System.out.println("student1: " + student1.getName() + " " + student1.getAge() + " " + student1.getDepartment().getName());

        System.out.println("student2: " + student2.getName() + " " + student2.getAge() + " " + student2.getDepartment().getName());

    }

}

输出结果:

student1: Alice 20 Software Engineering

student2: Alice 20 Software Engineering

student1: Alice 20 Software Engineering

student2: Alice 20 Computer Science

在上面的示例中,我们创建了两个学生对象,并将它们存储在student1和student2变量中。然后,我们修改了student2的部门名称,并输出了student1和student2的详细信息。在输出中,我们可以看到如果我们修改一个引用类型的值,那么原始对象不会受到任何影响。

浅复制(Shallow Copy)

浅复制是仅仅复制对象本身,不涉及到对象的引用类型。在Java中,我们可以使用Object类中的clone方法来执行浅复制。

让我们考虑以下示例代码:

public class Student implements Cloneable {

    private String name;

    private int age;

    private Department department;

    public Student(String name, int age, Department department) {

        this.name = name;

        this.age = age;

        this.department = department;

    }

    public void setDepartment(Department department) {

        this.department = department;

    }

    public String getName() {

        return name;

    }

    public int getAge() {

        return age;

    }

    public Department getDepartment() {

        return department;

    }

    @Override

    public Object clone() throws CloneNotSupportedException {

        return super.clone();

    }

}

public class Department {

    private String name;

    public Department(String name) {

        this.name = name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public String getName() {

        return name;

    }

}

在上面的示例中,我们仍然有一个学生类,其中包括学生的名字、年龄和一个Department对象。我们在Department类中不需要实现Cloneable接口,因为它只包含基本类型。

要将Student类进行浅复制,我们需要使其实现Cloneable接口并重写clone方法。在clone方法中,我们只需调用super.clone方法,因为这个方法已经复制了Student对象。但是,由于我们在Student类中有一个引用类型,所以复制的只是这个引用类型的对象地址,这意味着新对象和原始对象共享同一个Department对象。因此,如果我们在新对象中修改引用类型的值,原始对象也会受到影响。

让我们测试一下:

public class Test {

    public static void main(String[] args) throws CloneNotSupportedException {

        Department department = new Department("Software Engineering");

        Student student1 = new Student("Alice", 20, department);

        Student student2 = (Student) student1.clone();

        System.out.println("student1: " + student1.getName() + " " + student1.getAge() + " " + student1.getDepartment().getName());

        System.out.println("student2: " + student2.getName() + " " + student2.getAge() + " " + student2.getDepartment().getName());

        student2.getDepartment().setName("Computer Science");

        System.out.println("student1: " + student1.getName() + " " + student1.getAge() + " " + student1.getDepartment().getName());

        System.out.println("student2: " + student2.getName() + " " + student2.getAge() + " " + student2.getDepartment().getName());

    }

}

输出结果:

student1: Alice 20 Software Engineering

student2: Alice 20 Software Engineering

student1: Alice 20 Computer Science

student2: Alice 20 Computer Science

在上面的示例中,我们创建了两个学生对象,并将它们存储在student1和student2变量中。然后,我们修改了student2的部门名称,并输出了student1和student2的详细信息。在输出中,我们可以看到如果我们修改一个引用类型的值,那么原始对象也会受到影响。

总结

在Java中,深复制和浅复制都是非常重要的概念。在深复制中,我们复制对象及其所有引用的类型,而在浅复制中,我们仅仅复制对象本身,不涉及到对象的引用类型。因此,在使用clone方法时要非常小心,需要根据具体情况选用深复制或浅复制。

在实际开发中,如果我们需要复制一个对象及其所有的引用类型,那么我们应该使用深复制。相反,如果我们只需要复制一个对象本身,那么我们应该使用浅复制。在复制对象时,我们需要确保对象及其所有引用类型都正确地执行了clone方法,以避免出现错误。