1. 程式人生 > >clone深拷貝和淺拷貝

clone深拷貝和淺拷貝

前言

clone是Object類的一個本地方法,Object類預設使用的是淺拷貝,如果想要實現深拷貝,需要去實現Cloneable介面,並重寫clone方法。

淺拷貝是指:當物件的屬性是基本資料型別時,會複製屬性及值,當物件的屬性有引用型別的時候,會把當前屬性引用複製。

深拷貝是指:當物件的屬性是基本資料型別時,會複製屬性及值,當物件的屬性有引用型別的時候,會把當前屬性引用的物件再複製一份。

區別就是:當需要clone的物件的屬性都是基本資料型別,深拷貝淺拷貝一樣,當需要clone的物件的屬性有引用型別的時候,淺拷貝直接把引用地址複製過去,深拷貝會把引用的物件再複製一份。

下面是例子:

淺拷貝

public class Test{

    public static void main(String[] args) throws CloneNotSupportedException{

        Professor p1=new Professor();

        p1.setName("zhang");

        p1.setAge(44);

        Student s1=new Student();

        s1.setName("Xiao Ming");

        s1.setAge(15);

        s1.setProfessor(p1);

        System.out.println(s1);

        Student s2=(Student) s1.clone();//克隆s1

        Professor p2=s2.getProfessor();//這裡其實獲取的是p1的引用

        //其實這裡修改的也是p1的屬性

        p2.setName("Li");

        p2.setAage(55);

        s2.setProfessor(p2);

        s2.setAge(88);//這裡是基本資料型別

        s2.setName("Wu");//這裡是基本資料型別

        System.out.println("修改前 :"+s1);

        System.out.println("修改後 :"+s2);

    }

}

class Student implements{

    private String name;

    private int age;

    private Professor professor;

    ....set、get方法

    ...toString方法

    @Override

    protected Object clone()throws CloneNotSupportedException{

        return super.clone();

    }

}

class Professor {

    private String name;

    private int age;

    ...set、get方法

    ...toString方法

}

發現問題,當修改p2的時候,p1也跟著變了,是因為p1和p2指向的是同一個物件,所以clone的是引用。

深拷貝

public class Test{

    public static void main(String[] args) throws CloneNotSupportedException{

        Professor p1=new Professor();

        p1.setName("zhang");

        p1.setAge(44);

        Student s1=new Student();

        s1.setName("Xiao Ming");

        s1.setAge(15);

        s1.setProfessor(p1);

        System.out.println(s1);

        Student s2=(Student) s1.clone();//克隆s1

        Professor p2=s2.getProfessor();//這裡其實獲取的是p1的引用

        //其實這裡修改的也是p1的屬性

        p2.setName("Li");

        p2.setAage(55);

        s2.setProfessor(p2);

        s2.setAge(88);//這裡是基本資料型別

        s2.setName("Wu");//這裡是基本資料型別

        System.out.println("修改前 :"+s1);

        System.out.println("修改後 :"+s2);

    }

}

class Student implements{

    private String name;

    private int age;

    private Professor professor;

    ....set、get方法

    ...toString方法

    @Override

    protected Object clone()throws CloneNotSupportedException{

        Student newStudent=(Student) super.clone();

        newStudent.professor=(Professor) professor.clone();

        return newStudent;

    }

}

class Professor implements Cloneable {

    private String name;

    private int age;

    ...set、get方法

    ...toString方法

    @Override

    protected Object clone()throws CloneNotSupportedException{

        return super.clone();

    }

}

這一次發現修改s2的引用型別後,並沒有對s1產生影響了。其實深拷貝也就是把所有的引用的物件屬性再做一個clone,直到最終的所有的屬性都是基本資料型別。