The clone principle of Java

Today's record is the cloning mechanism of java, as well as deep and shallow cloning

public static class Boss{
        private int number;

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }
    }

    public static class Boy implements Cloneable{
        private Boss boss;
        private int number;
        private List<Integer> list=new ArrayList<>();

        public Boy(){
            boss=new Boss();
        }

        public Boss getBoss() {
            return boss;
        }

        public void setBoss(Boss boss) {
            this.boss = boss;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        @Override
        public String toString() {
            return super.toString();
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

Our boy here refers to my little brother, boss is the boss, so my little brother will correspond to a boss, but the boss didn't realize the cloning and only my little brother realized the cloning. What kind of results can we test?

public static void main(String[] args) throws Exception{
        Boy boy1=new Boy();
        boy1.boss.setNumber(0);
        boy1.setNumber(0);

        Boy boy2=(Boy) boy1.clone();
        boy2.boss.setNumber(1);
        boy2.setNumber(1);

        System.out.println(boy1.boss.number);
        System.out.println(boy2.boss.number);
        System.out.println(boy1.number);
        System.out.println(boy2.number);
    }

Output results:

boy1 number 1
boy2 number 1
boy1 boss number 0
boy2 boss number 1

As you can see, boy.name is cloned, but boy.boss is still not cloned. In fact, the reason is the java cloning mechanism. The clones that directly call java are all shallow clones, that is, to copy the basic data type directly, and to copy the reference of the object for the object. Therefore, to successfully clone the boss, you need to change this way:

public static class Boss implements Cloneable{
        private int number;

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }
    }

    public static class Boy implements Cloneable{
        private Boss boss;
        private int number;
        private List<Integer> list=new ArrayList<>();

        public Boy(){
            boss=new Boss();
        }

        public Boss getBoss() {
            return boss;
        }

        public void setBoss(Boss boss) {
            this.boss = boss;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }

        @Override
        public String toString() {
            return super.toString();
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            Boy boy=(Boy) super.clone();
            boy.boss=(Boss) this.boss.clone();

            return boy;
        }
    }

Run again:

boy1 number 0
boy2 number 1
boy1 boss number 0
boy2 boss number 1

In fact, clone is not a good way to achieve deep cloning. The best way to achieve deep cloning is to use serialization and deserialization:

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) throws Exception{
        Boy boy1=new Boy();
        boy1.setNumber(0);
        boy1.boss.setNumber(0);

        Boy boy2=clone(boy1);
        boy2.setNumber(1);
        boy2.boss.setNumber(1);

        System.out.println(boy1.boss.number);
        System.out.println(boy2.boss.number);
        System.out.println(boy1.number);
        System.out.println(boy2.number);
    }

    public static class Boss implements Serializable{
        private int number;

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }
    }

    public static class Boy implements Serializable{
        private Boss boss;
        private int number;
        private List<Integer> list=new ArrayList<>();

        public Boy(){
            boss=new Boss();
        }

        public Boss getBoss() {
            return boss;
        }

        public void setBoss(Boss boss) {
            this.boss = boss;
        }

        public int getNumber() {
            return number;
        }

        public void setNumber(int number) {
            this.number = number;
        }
    }

    public static <T> T clone(T obj) throws Exception{
        ByteArrayOutputStream bout=new ByteArrayOutputStream();
        ObjectOutputStream oos=new ObjectOutputStream(bout);
        oos.writeObject(obj);

        ByteArrayInputStream bin=new ByteArrayInputStream(bout.toByteArray());
        ObjectInputStream ois=new ObjectInputStream(bin);
        return (T) ois.readObject();
    }
}

Tags: Java

Posted on Wed, 01 Apr 2020 20:34:22 -0700 by snoopy13