"Talk about deep copy and shallow copy"

A:

1. Light copy

The reference type of the copy object and the original object refer to the same object.

All variables of the copied object contain the same value as the original object, while all references to other objects still point to the original object. In other words, a shallow copy copies only the objects it copies, not the objects it references.

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("After copying");
        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("After modifying the teacher's information-------------");

        // Revise the teacher's information
        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;
    }

}

Output results:

After copying
Dream
18
Delacey
29
 After modifying the teacher's information-------------
Jam
Jam

Result analysis: two references, student1 and student2, point to two different objects, but two references, student1 and student2, point to the same object, so it is a shallow copy.

2. Deep copy

The reference types of the copy object and the original object refer to different objects.

All variables of the copied object contain the same value as the original object, except those referring to other objects. Variables that refer to other objects will point to the copied new objects instead of the original ones. In other words, the deep copy copies all the objects referenced by the objects to be copied

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("After copying");
        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("After modifying the teacher's information-------------");

        // Revise the teacher's information
        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 {
        // When light copy:
        // Object object = super.clone();
        // return object;

        // Change to deep copy:
        Student3 student = (Student3) super.clone();
        // It was originally a shallow copy. Now copy the Teacher object and set it again
        student.setTeacher((Teacher2) student.getTeacher().clone());
        return student;
    }

}


Output results:

After copying
Dream
18
Delacey
29
 After modifying the teacher's information-------------
Jam
Delacey

Results analysis:
Two references, student1 and student2, point to two different objects. Two references, student1 and student2, point to two objects, but the modification of the teacher object can only affect student1 object, so it is a deep copy.

Using serialization to realize deep copy

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("After copying:");
        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("After modification:");
        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 {
        // serialize
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        oos.writeObject(this);

        // Deserialization
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);

        return ois.readObject();
    }
}


Output results:

After copying:
blank space
20
Taylor
28
---------------------------
After modification:
swift
Taylor

Result analysis: it shows that deep copy of object is realized by serialization

Out of question:

Reference copy and object copy

  1. Reference copy

    Create a copy of the reference variable to the object.

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

    Output results:

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

    Result analysis: from the output results, we can see that their address values are the same, so they must be the same object. The references of the teacher and the other teacher are just references. They both point to the same object, the Teacher("Taylor", 26). This is called a reference copy.

  2. Object Copy

    Create a copy of the object itself.

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

    Output results:

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

    Result analysis: as can be seen from the output results, their addresses are different, that is to say, new objects are created instead of assigning the address of the original object to a new reference variable, which is called object copy.

    Both deep and shallow copies are object copies

    reference resources: https://blog.csdn.net/baiye_xing/article/details/71788741

An alternative to clone()

Using the clone() method to copy an object is complex and risky, it throws an exception and requires a type conversion. According to the Effective Java book, it's better not to use clone(), you can use copy constructor or copy factory to copy an object.

Light copy

public class ShallowCloneExample implements Cloneable {

    private int[] arr;

    public ShallowCloneExample() {
        arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }
    }

    public void set(int index, int value) {
        arr[index] = value;
    }

    public int get(int index) {
        return arr[index];
    }

    @Override
    protected ShallowCloneExample clone() throws CloneNotSupportedException {
        return (ShallowCloneExample) super.clone();
    }
}
ShallowCloneExample e1 = new ShallowCloneExample();
ShallowCloneExample e2 = null;
try {
    e2 = e1.clone();
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}
e1.set(2, 222);
System.out.println(e2.get(2)); // 222

Deep copy

public class DeepCloneExample implements Cloneable {

    private int[] arr;

    public DeepCloneExample() {
        arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }
    }

    public void set(int index, int value) {
        arr[index] = value;
    }

    public int get(int index) {
        return arr[index];
    }

    @Override
    protected DeepCloneExample clone() throws CloneNotSupportedException {
        DeepCloneExample result = (DeepCloneExample) super.clone();
        result.arr = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            result.arr[i] = arr[i];
        }
        return result;
    }
}
DeepCloneExample e1 = new DeepCloneExample();
DeepCloneExample e2 = null;
try {
    e2 = e1.clone();
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}
e1.set(2, 222);
System.out.println(e2.get(2)); // 2

Alternatives

public class CloneConstructorExample {

    private int[] arr;

    public CloneConstructorExample() {
        arr = new int[10];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = i;
        }
    }

    public CloneConstructorExample(CloneConstructorExample original) {
        arr = new int[original.arr.length];
        for (int i = 0; i < original.arr.length; i++) {
            arr[i] = original.arr[i];
        }
    }

    public void set(int index, int value) {
        arr[index] = value;
    }

    public int get(int index) {
        return arr[index];
    }
}
CloneConstructorExample e1 = new CloneConstructorExample();
CloneConstructorExample e2 = new CloneConstructorExample(e1);
e1.set(2, 222);
System.out.println(e2.get(2)); // 2

How to clone objects?

There are two ways:

  1. Implement the clonable interface and override the clone() method in the Object class;
  2. Realize the Serializable interface, realize the cloning through the serialization and deserialization of the object, and realize the real deep cloning.

Official account reply (project actual combat) leads actual video + courseware information
Station B https://www.bilibili.com/video/BV1x54y1Q7XK/ Look at the algorithm class, now the first season is over

Tags: Swift Java

Posted on Fri, 12 Jun 2020 05:37:07 -0400 by cavolks