Introduction to deep (deep) and shallow (shallow) replication of objects in Java

  • 2020-04-01 03:47:54
  • OfStack

1. Shallow replication and deep replication concepts

Shallow copy  

      All variables of the copied object have the same values as the original object, and all references to other objects still refer to the original object. In other words, shallow replication simply copies the object in question, not the object it references.

The deep replication (deep cloning)  

      All variables of the copied object have the same values as the original object, except for those that reference other objects. Variables that reference other objects will point to new objects that have been copied, instead of the old ones. In other words, deep replication copies all the objects referenced by the object to be copied.

2. Java's clone () method

The friend clone method makes a copy of the object and returns it to the caller. In general, the clone () method satisfies:
For any object x, there is x.clone()! =x// clone object is not the same object as the original object
For any object x, there is x.clone(). GetClass ()= = x.getclass ()// the clone object is of the same type as the original object
If the equals() method of object x is properly defined, then x.clone().equals(x) should be true.

The Java clone of the object

To get a copy of the Object, we can use the clone() method of the Object class.
Overrides the clone() method of the base class in the derived class and declares it public.
In the clone() method of the derived class, call super.clone().
Implement the Cloneable interface in the derived class.

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 identifies 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; 
  //Modifying student 2 does not affect the value of student 1.
  System.out.println("name="+s1.name+","+"age="+s1.age); 
  System.out.println("name="+s2.name+","+"age="+s2.age);
 }
} 

Description:
Why do we have to call super.clone() when overwriting the clone() method of Object in a derived class? At run time, clone() in Object identifies which Object you want to copy, allocates space for that Object, and copies the contents of the original Object into the storage space of the new Object.
The clone() method inherited from the java.lang.object class is a 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;//Student 1 and student 2 both have the same reference value.
  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()); 
   } 
   o.p=(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);
  //Output results student 1 and 2 of the professor become lisi,age is 30.
  } 
} 

So how do you achieve a deeper level of cloning, that is, modifying professors in s2 will not affect professors in s1? The code improvements are as follows.
Improved student 1 Professor unchanged (in-depth cloning)


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()); 
   } 
   //The referenced objects are also copied
   o.p=(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; 
  //Student 1's professor does 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. Deep replication using serialization (the main purpose is to avoid overwriting the clone () method of deep replication of more complex objects, but also to achieve breakpoint continuation, etc.)
      The process of writing objects into a stream is a Serilization process, but it is very figuratively called "freezing" or "picking" in the Java programmer community. And the object from the stream to read out the parallelization (Deserialization) process is called "thaw" or "back to fresh (depicking)" process.
      It should be noted that what is written in the stream is a copy of the object, and the original object still exists in the JVM, so the "pickle" is just a copy of the object, and the Java pickle is still fresh.
      Deep copying an object in the Java language is often done by making the object implement the Serializable interface, then writing the object (which is really just a copy of the object) to a stream (pickle) and reading it out of the stream (freshen the pickle) to recreate the object.
The following is a deep copy of the source code.


public Object deepClone() 
{ 
 //Write the object to the stream
 ByteArrayOutoutStream bo=new ByteArrayOutputStream(); 
 ObjectOutputStream oo=new ObjectOutputStream(bo); 
 oo.writeObject(this); 
 //Read it out of the stream
 ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray()); 
 ObjectInputStream oi=new ObjectInputStream(bi); 
 return(oi.readObject()); 
} 

This assumes that the object and all objects referenced within the object are serializable. Otherwise, it is necessary to carefully examine whether objects or properties that are not serializable can be set as transient to exclude them from the replication process. The above 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;//Student 1 and student 2 both have the same reference value.
 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 to the stream
  ByteArrayOutoutStream bo=new ByteArrayOutputStream();
  ObjectOutputStream oo=new ObjectOutputStream(bo);
  oo.writeObject(this);//Read it out of 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);
 }
}

Related articles: