1. Shallow copy and deep copy concept
⑴Shallow copy (shallow cloning)
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, shallow copying simply copies the object being considered, not the object it references.
⑵ Deep copy (deep cloning)
All variables of the copied object contain the same value as the original object, except those variables that refer to other objects. Those variables that refer to other objects will point to the copied new object, instead of the original referenced objects. In other words, deep copy copies all the objects referenced by the object to be copied.
2. Java's clone() method
⑴ The clone method copies a copy of the object and returns it to the caller. Generally speaking, the clone() method satisfies:
① For any object x, there is x.clone() !=x//The cloned object is not the same object as the original object ② For any object x, there is x.clone().getClass()= =x. getClass()//Clone object is the same as the original object's type ③ If the equals() method of object x is defined appropriately, then x.clone().equals(x) should be true.
⑵Clone of objects in Java
① In order to obtain a copy of the object, we can use the clone() method of the Object class.
② Overwrite the clone() method of the base class in the derived class and declare it as public.
③ In the clone() method of the derived class, call super.clone().
④ Implement the Cloneable interface in the derived class.
Please see the following code:
public class Student implements Cloneable { String name; int age; Student(String name,int age) { this.name=name; this.age=age; } public Object clone() { Object o=null; try { o=( Student)super.clone();//Clone() in Object recognizes which object you want to copy. } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } public static void main(String[] args) { Student s1=new Student("zhangsan",18); Student s2=(Student)s1.clone(); s2.name="lisi"; s2.age=20; //After modifying student 2, the value of student 1 will not be affected. System.out.println("name="+s1.name+","+"age="+s1.age); System.out.println("name="+s2.name+","+"age=" +s2.age); }} illustrate:
①Why do we have to call super.clone() when overwriting the Object's clone() method in the derived class? At the run time, clone() in Object recognizes which object you want to copy, then allocates space for this object, and copies the object, copying the contents of the original object one by one into the storage space of the new object.
② The clone() method inherited from the java.lang.Object class is shallow copy. The following code can prove it.
class Professor { String name; int age; Professor(String name,int age) { this.name=name; this.age=age; } } public class Student implements Cloneable { String name;// Constant object. int age; Professor p;// The reference values of student 1 and student 2 are the same. Student(String name,int age,Professor p) { this.name=name; this.age=age; this.p=p; } public Object clone() { Student o=null; try { o=(Student)super .clone(); } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } op=(Professor)p.clone(); return o; } public static void main(String[] args ) { Professor p=new Professor("wangwu",50); Student s1=new Student("zhangsan",18,p); Student s2=(Student)s1.clone(); s2.p.name="lisi "; s2.p.age=30; System.out.println("name="+s1.p.name+","+"age="+s1.p.age); System.out.println("name ="+s2.p.name+","+"age="+s2.p.age); //The output results of the professors of students 1 and 2 become lisi, and the age is 30. } } So how should we implement deep cloning, that is, the professor who modify s2 will not affect the professor who s1? The code is improved as follows.
Improvements to make Student 1's Professor unchanged (deep clone)
class Professor implements Cloneable { String name; int age; Professor(String name,int age) { this.name=name; this.age=age; } public Object clone() { Object o=null; try { o=super. clone(); } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } return o; } } public class Student implements Cloneable { String name; int age; Professor p; Student(String name, int age,Professor p) { this.name=name; this.age=age; this.p=p; } public Object clone() { Student o=null; try { o=(Student)super.clone(); } catch(CloneNotSupportedException e) { System.out.println(e.toString()); } //Copy the referenced object also op=(Professor)p.clone(); return o; } public static void main( String[] args) { Professor p=new Professor("wangwu",50); Student s1=new Student("zhangsan",18,p); Student s2=(Student)s1.clone(); s2.p. name="lisi"; s2.p.age=30; //The professor of student 1 will not change. System.out.println("name="+s1.p.name+","+"age="+s1.p.age); System.out.println("name="+s2.p.name+", "+"age="+s2.p.age); } } 3. Use serialization to do deep copy (mainly to avoid rewriting the clone() method of deep copy of more complex objects, and can also implement breakpoint continuous transmission and other functions)
The process of writing objects into streams is a serialization process, but it is very vividly called "frozen" or "picking" process in Java programmers' circles; and reading objects from streams The resulting parallelization process is called "thawing" or "depicking" process.
It should be pointed out that what is written in the stream is a copy of the object, and the original object still exists in the JVM, so what is "pickled into pickles" is only a copy of the object, and Java pickles can still be fresh.
Deeply copying an object in Java language can often make the object implement the Serializable interface first, and then write the object (actually just a copy of the object) into a stream (pickled into pickles), and then read it from the stream (put the pickles back ) can reconstruct the object.
The following is the deep copy source code.
public Object deepClone() { //Write the object into the stream ByteArrayOutoutStream bo=new ByteArrayOutputStream(); ObjectOutputStream oo=new ObjectOutputStream(bo); oo.writeObject(this); //Read from the stream ByteArrayInputStream bi=new ByteArrayInputStream (bo.toByteArray()); ObjectInputStream oi=new ObjectInputStream(bi); return(oi.readObject()); } The premise of doing this is that the object and all referenced objects within the object are serializable. Otherwise, it is necessary to carefully examine whether those objects or attributes that cannot be serialized can be set to be transient, thereby excluding them from the copying process. outside. The above example code is improved as follows.
class Teacher implements Serializable{ String name; int age; public void Teacher(String name,int age){ this.name=name; this.age=age; }}public class Student implements Serializable{ String name;//Constant object int age; Teacher t;//The reference values of student 1 and student 2 are the same. public void Student(String name,int age,Teacher t){ this.name=name; this.age=age; this.p=p; } public Object deepClone() throws IOException, OptionalDataException,ClassNotFoundException{//Write the object Go to the stream ByteArrayOutoutStream bo=new ByteArrayOutputStream(); ObjectOutputStream oo=new ObjectOutputStream(bo); oo.writeObject(this);//Read from the stream ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi= new ObjectInputStream(bi); return(oi.readObject()); } public static void main(String[] args){ Teacher t=new Teacher("tangliang",30); Student s1=new Student("zhangsan", 18,t); Student s2=(Student)s1.deepClone(); s2.t.name="tony"; s2.t.age=40; //Student 1's teacher does not change System.out.println(" name="+s1.t.name+","+"age="+s1.t.age); }}