Acerca de la copia profunda y la copia superficial de Java

1. Introducción de copia

1.1 Copia de referencia

Crear una copia de una variable de referencia que apunte a un objeto

Teacher teacher = new Teacher("Taylor",26);
Teacher otherteacher = teacher;
System.out.println(teacher);
System.out.println(otherteacher);

producción:

blog.Teacher@355da254
blog.Teacher@355da254

Se puede ver en los resultados de salida que sus valores de dirección son los mismos, por lo que deben ser el mismo objeto. El maestro y otro maestro son solo referencias, todos apuntan al mismo objeto Maestro ("Taylor", 26). Esto se llama copia por referencia .
inserte la descripción de la imagen aquí

1.2 Copia de objeto

Cree una copia del propio objeto.

Teacher teacher = new Teacher("Swift",26);
Teacher otherteacher = (Teacher)teacher.clone();
System.out.println(teacher);
System.out.println(otherteacher);

producción:

blog.Teacher@355da254
blog.Teacher@4dc63996

Se puede ver en los resultados de salida que sus direcciones son diferentes, es decir, se crea un nuevo objeto en lugar de asignar la dirección del objeto original a una nueva variable de referencia, lo que se denomina copia de objeto .
inserte la descripción de la imagen aquí

2. Copia profunda y copia superficial

En el lenguaje Java, cuando necesitamos copiar un objeto, existen dos tipos de copias: copia superficial y copia profunda.
La copia superficial solo copia la dirección del objeto de origen, por lo que cuando cambia el valor del objeto de origen, también cambiará el valor del objeto copiado.
La copia profunda copia todos los valores del objeto de origen, por lo que incluso si el valor del objeto de origen cambia, el valor del objeto copiado no cambiará. Como se muestra en la siguiente figura:
inserte la descripción de la imagen aquí

2.1 copia superficial

Definición:
Todas las variables del objeto copiado contienen el mismo valor que el objeto original, y todas las referencias a otros objetos todavía apuntan al objeto original. Es decir, una copia superficial de un objeto hará una copia del objeto "principal", pero no copiará los objetos dentro del objeto principal. El "objeto interior" se compartirá entre el objeto original y su copia.

En resumen, una copia superficial solo copia el objeto en cuestión, no el objeto al que se refiere.

Ejemplo de copia superficial:

public class ShallowCopy {
    
    
    public static void main(String[] args) throws CloneNotSupportedException {
    
    
        Teacher teacher = new Teacher();
        teacher.setName("Delacey");
        teacher.setAge(29);

        Student2 student1 = new Student2();
        student1.setName("Dream");
        student1.setAge(18);
        student1.setTeacher(teacher);

        Student2 student2 = (Student2) student1.clone();//拷贝
        System.out.println("拷贝后");
        System.out.println(student2.getName());
        System.out.println(student2.getAge());
        System.out.println(student2.getTeacher().getName());
        System.out.println(student2.getTeacher().getAge());
        System.out.println("修改老师的信息后-------------");

        // 修改老师的信息
        teacher.setName("Jam");
        System.out.println(student1.getTeacher().getName());
        System.out.println(student2.getTeacher().getName());
    }

}

class Teacher implements Cloneable {
    
    
    private String name;
    private int age;

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

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

class Student2 implements Cloneable{
    
    
    private String name;
    private int age;
    private Teacher teacher;

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

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

    public Teacher getTeacher() {
    
    
        return teacher;
    }

    public void setTeacher(Teacher teacher) {
    
    
        this.teacher = teacher;
    }

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

}

producción

拷贝后
Dream
18
Delacey
29
修改老师的信息后-------------
Jam
Jam

Análisis de resultados: las dos referencias estudiante1 y estudiante2 apuntan a dos objetos diferentes, pero las dos referencias de maestro en las dos referencias estudiante1 y estudiante2 apuntan al mismo objeto, por lo que es una copia superficial .
inserte la descripción de la imagen aquí

2.2 copia profunda

Definición:
Una copia profunda es una copia de un objeto independiente completo. Una copia profunda copiará todos los atributos y copiará la memoria asignada dinámicamente a la que apuntan los atributos. Una copia profunda ocurre cuando un objeto se copia junto con los objetos a los que se refiere. Las copias profundas son más lentas y costosas que las copias superficiales.

En resumen, la copia profunda copia todos los objetos a los que hace referencia el objeto que se va a copiar.

Implemente la instancia de copia profunda 1:

public class DeepCopy {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Teacher2 teacher = new Teacher2();
        teacher.setName("Delacey");
        teacher.setAge(29);

        Student3 student1 = new Student3();
        student1.setName("Dream");
        student1.setAge(18);
        student1.setTeacher(teacher);

        Student3 student2 = (Student3) student1.clone();//拷贝
        System.out.println("拷贝后");
        System.out.println(student2.getName());
        System.out.println(student2.getAge());
        System.out.println(student2.getTeacher().getName());
        System.out.println(student2.getTeacher().getAge());
        System.out.println("修改老师的信息后-------------");

        // 修改老师的信息
        teacher.setName("Jam");
        System.out.println(student1.getTeacher().getName());
        System.out.println(student2.getTeacher().getName());
    }
}

class Teacher2 implements Cloneable {
    
    
    private String name;
    private int age;

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

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

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

}

class Student3 implements Cloneable {
    
    
    private String name;
    private int age;
    private Teacher2 teacher;

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

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

    public Teacher2 getTeacher() {
    
    
        return teacher;
    }

    public void setTeacher(Teacher2 teacher) {
    
    
        this.teacher = teacher;
    }

    @Override
    public Object clone() throws CloneNotSupportedException {
    
    
        // 浅复制时:
        // Object object = super.clone();
        // return object;

        // 改为深复制:
        Student3 student = (Student3) super.clone();
        // 本来是浅复制,现在将Teacher对象复制一份并重新set进来
        student.setTeacher((Teacher2) student.getTeacher().clone());
        return student;
    }

}


Resultado de salida:

拷贝后
Dream
18
Delacey
29
修改老师的信息后-------------
Jam
Delacey

Análisis de resultados:
las dos referencias estudiante1 y estudiante2 apuntan a dos objetos diferentes, y las dos referencias de maestro en las dos referencias estudiante1 y estudiante2 apuntan a dos objetos, pero la modificación del objeto maestro solo puede afectar al objeto estudiante1, por lo que es profundo Copiar.

La imagen a continuación muestra el nombre de la maestra Delacey antes de cambiar:
inserte la descripción de la imagen aquí
la imagen a continuación muestra el nombre de la maestra Jam cambiando:
inserte la descripción de la imagen aquí
usando la serialización para lograr una copia profunda:

public class DeepCopyServiable {
    
    
    public static void main(String[] args) throws Exception {
    
    
        Teacher3 t = new Teacher3();
        t.setName("Taylor");
        t.setAge(28);

        Student3 s1 = new Student3();
        s1.setAge(20);
        s1.setName("blank space");
        s1.setTeacher(t);

        Student3 s2 = (Student3) s1.deepClone();//拷贝

        System.out.println("拷贝后:");
        System.out.println(s2.getName());
        System.out.println(s2.getAge());
        System.out.println(s2.getTeacher().getName());
        System.out.println(s2.getTeacher().getAge());
        System.out.println("---------------------------");

        t.setName("swift");

        System.out.println("修改后:");
        System.out.println(s1.getTeacher().getName());
        System.out.println(s2.getTeacher().getName());
    }
}

class Teacher3 implements Serializable {
    
    
    private String name;
    private int age;

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

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

}

class Student3 implements Serializable {
    
    
    private String name;
    private int age;
    private Teacher3 teacher;

    public String getName() {
    
    
        return name;
    }

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

    public int getAge() {
    
    
        return age;
    }

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

    public Teacher3 getTeacher() {
    
    
        return teacher;
    }

    public void setTeacher(Teacher3 teacher) {
    
    
        this.teacher = teacher;
    }

    public Object deepClone() throws Exception {
    
    
        // 序列化
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        oos.writeObject(this);

        // 反序列化
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);

        return ois.readObject();
    }
}

resultado de salida

拷贝后:
blank space
20
Taylor
28
---------------------------
修改后:
swift
Taylor

Análisis de resultados: Muestra que la copia profunda del objeto se realiza por serialización.

Publicación de blog de referencia (invasión y eliminación):
https://blog.csdn.net/baiye_xing/article/details/71788741
https://www.cnblogs.com/ysocean/p/8482979.html
https://www.cnblogs .com /xinruyi/p/11537963.html

Supongo que te gusta

Origin blog.csdn.net/mfysss/article/details/129116659
Recomendado
Clasificación