A method of deep cloning of Java objects based on serialized access

  • 2020-04-01 01:58:31
  • OfStack

We know that in Java, after assigning an object reference of a non-prototype type to a reference of another object, the two references point to the same object, such as:

public class DeepCloneTest {

 private class CloneTest {
  private Long myLong = new Long(1);
 }

 public static void main(String args[]) {
  new DeepCloneTest().Test();
 }

 public void Test() {
  CloneTest ct1 = new CloneTest();
  CloneTest ct2 = ct1;

  // to see if ct1 and ct2 are one same reference.
  System.out.println("ct1: " + ct1);
  System.out.println("ct2: " + ct2);

  // if ct1 and ct2 point to one same object, then ct1.myLong == ct2.myLong.
  System.out.println("ct1.myLong: " + ct1.myLong);
  System.out.println("ct2.myLong: " + ct2.myLong);

  // we change ct2's myLong
  ct2.myLong = 2L;

  // to see whether ct1's myLong was changed.
  System.out.println("ct1.myLong: " + ct1.myLong);
  System.out.println("ct2.myLong: " + ct2.myLong);
 }
}

The out put:
Ct1: $CloneTest @ c17164 DeepCloneTest
Ct2: $CloneTest @ c17164 DeepCloneTest
Ct1. MyLong: 1
Ct2. MyLong: 1
Ct1. MyLong: 2
Ct2. MyLong: 2
This is easy, probably learn Java all know (do not know is learn Java? .
In memory, the reference of the object is stored in the stack, the data of the object is stored in the heap, and the reference in the stack points to the object in the heap. Here is the reference in two stacks, pointing to the same object in the heap. Therefore, when the myLong of ct2 is changed, you can see that the myLong value of ct1 is also changed. If it is represented by a graph, it is easy to understand:

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201305/201305171007422.gif ">

On the left is the stack area, where there are two references with the same value that point to the same object on the right.
Most of the time, we use this feature of the Java language to do what we want, such as passing a reference to an object as an input into a method, where we modify the object that the reference refers to. But sometimes we want to construct an object that has exactly the same content as an existing object, but references a different object, and to do that, You can do that :

public class DeepCloneTest{

 // must implements Cloneable.
 private class CloneTest implements Cloneable{
  private Object o = new Object();

  public CloneTest clone() {
   CloneTest ct = null;
   try {
    ct = (CloneTest)super.clone();
   } catch (CloneNotSupportedException e) {
    e.printStackTrace();
   }
   return ct;
  }
 }

 public static void main(String args[]) {
  new DeepCloneTest().Test();
 }

 public void Test() {
  CloneTest ct1 = new CloneTest();
  CloneTest ct2 = ct1.clone();

  // to see if ct1 and ct2 are one same reference.
  System.out.println("ct1: " + ct1);
  System.out.println("ct2: " + ct2);

  // whether ct1.o == ct2.o ? yes
  System.out.println("ct1.o " + ct1.o);
  System.out.println("ct1.o " + ct1.o);
 }
}

The out put:
Ct1: $CloneTest @ c17164 DeepCloneTest
Ct2: DeepCloneTest $1 fb8ee3 CloneTest @
Ct1. O Java. Lang. Object @ 61 de33
Ct1. O Java. Lang. Object @ 61 de33
It can be seen from the output that ct1 and ct2 are indeed two different references, so we take it for granted that ct1.o and ct2.o are also two different objects, but from the output we can see that this is not the case! Ct1.o and ct2.o are the same object! The reason is that although cloning is used, but the above is only shallow cloning, represented by graphics:

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201305/201305171007423.gif ">
See that o up there? It's actually Shared between two objects. So this is the same thing as saying, you had a pen 1 with a sheep in it, and then you had a pen 2 with a sheep in it, and you didn't take the sheep out of the pen 1, and you took the sheep in the pen 2, and you thought you had two sheep, but what? Everybody knows that.

This is the result of shallow cloning: If you want two objects to have separate o, you must clone o again. Maybe some people think there's nothing to it, just do it, but have you ever thought about it? If there's more than one o, there are many, many things like o, do you clone them one by one? Obviously not very realistic.

One solution: By serializing and storing the object into the stream, and then reading the object out of the reservation, you can ensure that the data you read is exactly the same as the previous object, just like a full copy.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class DeepCloneTest {

 // must implements Cloneable.
 private class CloneTest implements Serializable{
  private static final long serialVersionUID = 1L;
  private Object o = new Object();

  public CloneTest deepClone() {
   CloneTest ct = null;
   try {
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
             ObjectOutputStream oos = new ObjectOutputStream(baos); 
             oos.writeObject(this);
             ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); 
             ObjectInputStream ois= new ObjectInputStream(bais); 
             ct = (CloneTest)ois.readObject(); 
   } catch (IOException e) {
    e.printStackTrace();
   } catch (ClassNotFoundException e) {
    e.printStackTrace();
   }
   return ct;
  }
 }

 public static void main(String args[]) {
  new DeepCloneTest().Test();
 }

 public void Test() {
  CloneTest ct1 = new CloneTest();
  CloneTest ct2 = ct1.deepClone();

  // to see if ct1 and ct2 are one same reference.
  System.out.println("ct1: " + ct1);
  System.out.println("ct2: " + ct2);

  // whether ct1.o == ct2.o ? no
  System.out.println("ct1.o " + ct1.o);
  System.out.println("ct1.o " + ct1.o);
 }
}

At this point, the data in memory looks like this:

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201305/201305171007424.gif ">

Clone mission complete.


Related articles: