天天看點

Java clone淺複制與深複制的差別1. 概述2. 淺複制clone3. 深複制clone

1. 概述

Java對象要調用 clone 進行複制,必須實作 Cloneable 接口,否則會抛出

CloneNotSupportedException

的異常。

clone 方法預設是淺複制,如果要實作深複制,那必須在clone方法調用對象成員的複制方法。

  • 淺複制:複制對象時,對象内部引用類型的成員,仍然共用記憶體空間。此時A對象修改這個成員的屬性,B對象的該成員也會受影響。
  • 深複制:複制對象時,對象内部引用類型的成員,也會重新開辟新的空間。此時A對象和B對象完全互不幹擾。

2. 淺複制clone

Grade: 班級類,實作了Cloneable接口

@Data
public class Grade implements Cloneable{
	//名稱
    private String name;
    //班主任
    private Teacher headTeacher;

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

Teacher: 教師類,同樣實作Cloneable接口

@Data
public class Teacher implements Cloneable{
	//姓名
    private String name;

    @Override
    public Object clone() throws CloneNotSupportedException {
        Teacher teacher = (Teacher) super.clone();
        return teacher;
    }
}
           
  • 建立教師對象teacher,班級對象grade1
  • 從grade1複制出班級對象grade2
  • 修改grade1的名稱
  • 修改grade1的班主任的姓名
public static void main(String[] args) throws CloneNotSupportedException {
        Teacher teacher = new Teacher();
        teacher.setName("張三");

        Grade grade1 = new Grade();
        grade1.setName("一班");
        grade1.setHeadTeacher(teacher);

        Grade grade2 = (Grade) grade1.clone();

        grade1.setName("小一班");
        grade1.getHeadTeacher().setName("李四");

        System.out.println(grade1);
        System.out.println(grade2);
    }
           

看下執行結果

Grade(name=小一班, headTeacher=Teacher(name=李四))
Grade(name=一班, headTeacher=Teacher(name=李四))
           
  • 班級name的修改是互不影響的。上面說了,淺複制是引用類型才公共記憶體空間,String是特殊的引用類型。
  • 修改grade1的班主任name,直接影響了grade2的班主任,因為headTeacher就是一個引用類型變量。

3. 深複制clone

修改上面Grade類的clone代碼,複制的時候把Teacher對象也複制一份,這就是深複制。

@Override
    public Object clone() throws CloneNotSupportedException {
        Grade grade = (Grade) super.clone();
        grade.setHeadTeacher((Teacher)this.headTeacher.clone());
        return grade;
    }
           

其他代碼不變,然後重新運作程式,輸出如下:

Grade(name=小一班, headTeacher=Teacher(name=李四))
Grade(name=一班, headTeacher=Teacher(name=張三))
           

可以看到,headTeacher怎麼修改都互不影響,深複制成功。