Learn about deep copy and shallow copy of java

We know that copying is to generate a new object exactly the same as the original object, but copying is also divided into ways and degrees. Let's take a look at what is shallow copy and what is deep copy

Shallow copy

In Java, the clone() method of the java.lang.Object class is used for cloning (shallow copy, the attribute points are the same).
This method creates a copy of an object, calls it on it through field-by-field assignment, and returns a reference to the object.
To achieve shallow copy, you need to implement the Cloneable interface. There is no method in the interface, and it points to the clone() of the java.lang.Object class.

protected native Object clone() throws CloneNotSupportedException;

It is a native method, implemented by C/C++.
Let’s take a look at the example to understand why it is called shallow copy.
First, there is a dictionary object class, which implements the clone interface

@Data
class Dictionary implements Cloneable {
    
    

   private String name;

   private List<String> words;

   @Override
   public Object clone() {
    
    
       try {
    
    
           return super.clone();
       } catch (CloneNotSupportedException e) {
    
    
           e.printStackTrace();
       }
       return null;
   }
}

public static void shallowCopy() {
    
    
       Dictionary dictionary1 = new Dictionary();
       dictionary1.setName("汉语词典");
       dictionary1.setWords(new ArrayList<String>() {
    
    {
    
    
           add("你好");
           add("浅拷贝");
       }});
       Dictionary dictionary2 = (Dictionary) dictionary1.clone();
       System.out.println(dictionary1 == dictionary2);
       dictionary2.getWords().add("新词语");
       System.out.println("dictionary1: " + dictionary1.toString());
       System.out.println("dictionary2: " + dictionary2.toString());

       dictionary1.setName("新名字");
       System.out.println("dictionary1: " + dictionary1.toString());
       System.out.println("dictionary2: " + dictionary2.toString());
   }

operation result:

false
dictionary1: Dictionary(name=汉语词典, words=[你好, 浅拷贝, 新词语])
dictionary2: Dictionary(name=汉语词典, words=[你好, 浅拷贝, 新词语])
dictionary1: Dictionary(name=新名字, words=[你好, 浅拷贝, 新词语])
dictionary2: Dictionary(name=汉语词典, words=[你好, 浅拷贝, 新词语])

From the result, we know that dictionary1 and dictionary2 are not pointing to the same object. Two objects are indeed created, but when the properties of the second object are modified, the first object also changes.
To verify the shallow copy we mentioned earlier, the properties of the two objects point to the same object in the heap.

Deep copy

Compared with shallow copy, deep copy means that the attributes are also new objects. We can also implement the cloneable interface for each attribute of the object to achieve the effect of deep copy. We can also use serialization and deserialization to achieve deep copy.
First implement the Serializable interface for Dictionary

@Data
class Dictionary implements Cloneable, Serializable {
    
    

    private String name;

    private List<String> words;

    @Override
    public Object clone() {
    
    
        try {
    
    
            return super.clone();
        } catch (CloneNotSupportedException e) {
    
    
            e.printStackTrace();
        }
        return null;
    }
}
private static void deepCopy() throws IOException, ClassNotFoundException {
    
    
        Dictionary dictionary1 = new Dictionary();
        dictionary1.setName("汉语词典");
        dictionary1.setWords(new ArrayList<String>() {
    
    {
    
    
            add("你好");
            add("浅拷贝");
        }});

        Dictionary dictionary2 = null;

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectOutputStream.writeObject(dictionary1);

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(byteArrayInputStream);
        dictionary2 = (Dictionary) ois.readObject();

        // 测试方法没关闭流 实际项目记得关闭流
        System.out.println(dictionary1 == dictionary2);
        dictionary2.getWords().add("新词语");
        System.out.println("dictionary1: " + dictionary1.toString());
        System.out.println("dictionary2: " + dictionary2.toString());
    }

operation result

false
dictionary1: Dictionary(name=汉语词典, words=[你好, 深拷贝])
dictionary2: Dictionary(name=汉语词典, words=[你好, 深拷贝, 新词语])

I can see that both the object and its properties are independent. This is a deep copy.

Guess you like

Origin blog.csdn.net/sc9018181134/article/details/104054171