Creation mode-prototype mode

Creation mode-prototype mode

(I. Overview

The prototype mode refers to using an already created instance as a prototype, and creating a new object that is the same or similar to the prototype by copying the prototype object. The prototype instance specifies the type of object to be created. It is very efficient to create an object in this way, without knowing the details of object creation.

The prototype mode is a copy of the binary stream in the memory, which is much better than the direct new object performance, especially when the constructor is more complicated and a large number of objects are produced in the loop body, the prototype mode is very efficient.

Insert picture description here
Speaking of shallow copy and deep copy of the prototype mode, we all know that shallow copy is a copy of a member variable of a value type, and a variable of a reference type is only a copy of a reference. In fact, two objects still point to the same instance. The deep copy not only copies the member variables of the value type, but also applies for storage space for the member variables of the reference type, making it a new object. Knowing these is not enough, we need to understand the principle, let's take a look at their implementation process.

(2) Shallow copy version

To achieve shallow copy, we must first implement the Cloneable interface. There is no method in this interface. Its function is to inform the virtual machine that it is safe to use the clone() method on the class that implements this interface at runtime. In the Java virtual machine, only classes that implement this interface can be copied.

public class Sheep implements Cloneable {
    
    
    private String name;
    private int age;
    private String color;
    private Sheep friend;

    public Sheep(String name, int age, String color) {
    
    
        this.name = name;
        this.age = age;
        this.color = color;
    }

    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 String getColor() {
    
    
        return color;
    }

    public void setColor(String color) {
    
    
        this.color = color;
    }

    public Sheep getFriend() {
    
    
        return friend;
    }

    public void setFriend(Sheep friend) {
    
    
        this.friend = friend;
    }

    @Override
    protected Object clone() {
    
    
        Sheep sheep = null;
        try {
    
    
            sheep = (Sheep) super.clone();
        } catch (Exception e) {
    
    
            System.out.println(e.getMessage());
        }
        return sheep;
    }
}

Then let's test it. Through the values ​​of the two hashcodes, it is not difficult to find that our original object and the cloned object are not the same object, indicating that the member variables of our value type are copied.

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Sheep sheep = new Sheep("tom", 1, "白色");
        sheep.setFriend(new Sheep("jack", 2, "黑色"));
        Sheep sheep2 = (Sheep)sheep.clone();
        System.out.println(sheep.hashCode()); //输出结果为 455896770
        System.out.println(sheep2.hashCode()); //输出结果为 1323165413
    }
}

We can look at another test example, in this example we can find the problem of shallow copy. We found that the reference type friend in the two objects is the same. It can be seen that shallow copy only copies the reference to the reference type, and does not open up new storage space. Therefore, we need to use deep copy when encountering this situation.

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Sheep sheep = new Sheep("tom", 1, "白色");
        sheep.setFriend(new Sheep("jack", 2, "黑色"));
        Sheep sheep2 = (Sheep) sheep.clone();
        System.out.println(sheep.getFriend().hashCode());//输出结果为 455896770
        System.out.println(sheep2.getFriend().hashCode());//输出结果为 455896770
    }
}

(3) Deep copy version

We have two options for deep copying. One is to implement the Cloneable interface for all classes with reference type attributes. Obviously, if we have a lot of reference types, this method will bring about a rapid increase in the amount of code, and at the same time Increase the possibility of errors. The second is to deep copy through serialization and deserialization. This method will be more convenient, but it should be noted that all reference type attributes must also be serializable, otherwise this type of serialization will not be possible. .

We will now begin to modify the clone method of the shallow copy above to become a deep copy. We no longer need to implement the Cloneable interface, but we need to implement the Serializable interface to meet the needs of serialization and deserialization.

public class Sheep implements Serializable {
    
    
    private String name;
    private int age;
    private String color;
    private Sheep friend;

    public Sheep(String name, int age, String color) {
    
    
        this.name = name;
        this.age = age;
        this.color = color;
    }

    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 String getColor() {
    
    
        return color;
    }

    public void setColor(String color) {
    
    
        this.color = color;
    }

    public Sheep getFriend() {
    
    
        return friend;
    }

    public void setFriend(Sheep friend) {
    
    
        this.friend = friend;
    }

    public Object deepClone() {
    
    
        //创建流对象
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
    
    
            //序列化
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            //反序列化
            bis = new ByteArrayInputStream(bos.toByteArray());
            ois = new ObjectInputStream(bis);
            return (Sheep) ois.readObject();
        } catch (Exception e) {
    
    
            e.printStackTrace();
            return null;
        } finally {
    
    
            try {
    
    
                bos.close();
                oos.close();
                bis.close();
                ois.close();
            } catch (Exception e2) {
    
    
                System.out.println(e2.getMessage());
            }
        }
    }
}

Let's test the effect. Obviously, unlike shallow copy, the reference types in the two objects point to different objects. Here is a small detail to understand. After testing, we found that deserialization does not call the constructor. The object of the reverse sequence is the object generated by the JVM itself, not generated by the construction method.

public class Test {
    
    
    public static void main(String[] args) {
    
    
        Sheep sheep = new Sheep("tom", 1, "白色");
        sheep.setFriend(new Sheep("jack", 2, "黑色"));
        Sheep sheep2 = (Sheep) sheep.deepClone();
        System.out.println(sheep.getFriend().hashCode());//输出结果为 670576685
        System.out.println(sheep2.getFriend().hashCode());//输出结果为 1323468230
    }
}

July 28, 2020

Guess you like

Origin blog.csdn.net/weixin_43907422/article/details/107627353