日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

簡單認清深拷貝和淺拷貝

作者:奮斗喝咖啡 更新時間: 2022-07-19 編程語言

創建Java對象的方式包括new、反射、反序列化、拷貝,那么什么是拷貝呢?淺拷貝和深拷貝又有什么區別呢?

什么是拷貝

拷貝就是為了復用原對象的部分或全部數據,在原對象的基礎上通過復制的方式創建一個新的對象。

Object類中有native類型的clone方法

protected native Object clone() throws CloneNotSupportedException;
復制代碼

如果一個對象可以被拷貝,那么該對象對應的類需要實現Cloneable接口,并重寫Object的clone方法。

必須實現Cloneable接口,否則調用clone方法會拋出
java.lang.CloneNotSupportedExecption異常

//Cloneable接口中沒有任何參數或抽象方法,該接口只是一個標識
public interface Cloneable {
}
復制代碼
//如Student類,實現Cloneable接口,重寫Object的clone方法
public class Student implements Cloneable{

    private String sname;

    private Integer sage;
    
    ...
    
    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }
}
復制代碼

舉個栗子

public class cloneObject {
    public static void main(String[] args) throws CloneNotSupportedException {
        Student student = new Student("學生1",18);
        System.out.println("clone前的Student對象為:"+student);
        Student cloneStudent = student.clone();
        System.out.println("clone后的Student對象為:"+cloneStudent);
        System.out.println("Student對象與cloneStudent對象是否相等:"+student.equals(cloneStudent));
    }
}
復制代碼

打印結果為

clone前的Student對象為:Student{sname='學生1', sage=18}
clone后的Student對象為:Student{sname='學生1', sage=18}
Student對象與cloneStudent對象是否相等:false
復制代碼

由此可見,拷貝是創建了一個新的對象。

什么是淺拷貝?

我稍等改動下Student類來舉例說明

Student類中除了String類型和Integer類型的屬性外,添加了一個Teacher類型的屬性,Teacher類中只有一個String類型的tname屬性

public class Student implements Cloneable{

    private String sname;

    private Integer sage;

    private Teacher teacher;
    
    ...
    
    @Override
    protected Student clone() throws CloneNotSupportedException {
        return (Student) super.clone();
    }
復制代碼
public class Teacher {

    private String tname;
復制代碼

再次調用sutdent對象的clone方法

public static void main(String[] args) throws CloneNotSupportedException {
    Teacher teacher = new Teacher("老師");
    Student student = new Student("學生1",18,teacher);
    System.out.println("clone前的Student對象為:"+student);
    Student cloneStudent = student.clone();
    System.out.println("clone后的Student對象為:"+cloneStudent);
    System.out.println("Student對象與cloneStudent對象是否相等:"+student.equals(cloneStudent));
    System.out.println("student對象和cloneStudent對象中的teacher屬性是否相等:"+student.getTeacher().equals(cloneStudent.getTeacher()));
}
復制代碼

兩個sutdent對象比較結果在意料之中,為false。但是兩種student對象中的teacher屬性比較結果卻是true。

clone前的Student對象為:Student{sname='學生1', sage=18, teacher=com.hard.qz.clone.Teacher@1b6d3586}
clone后的Student對象為:Student{sname='學生1', sage=18, teacher=com.hard.qz.clone.Teacher@1b6d3586}
Student對象與cloneStudent對象是否相等:false
student對象和cloneStudent對象中的teacher屬性是否相等:true
復制代碼
//修改student對象中teacher屬性的值,觀察cloneStudent對象中的teacher屬性的值是否會變
student.getTeacher().setTname("張三老師");
System.out.println("cloneStudent對象中teacher屬性的值為:"+cloneStudent.getTeacher());
復制代碼

結果為:

cloneStudent對象中teacher屬性的值為:Teacher{tname='張三老師'}
復制代碼

當修改student對象中teacher屬性的值時,會影響到cloneStudent對象中teacher屬性的值 由此說明:兩個student對象共用一個teacher對象。

像上面這種情況,當拷貝時,只拷貝了部分屬性,沒有拷貝Object和數組屬性時,這種拷貝被稱為淺拷貝。

什么是深拷貝?

當拷貝時,拷貝了一個對象中的所有屬性,包括Object和數組屬性,這種拷貝被稱為深拷貝

如何實現深拷貝?

重寫clone方法時,對Object和數組屬性也調用clone方法就可以實現深拷貝,要求被拷貝對象的Object屬性也實現Cloneable接口,重寫了clone方法。

//Teacher類實現了Cloneable接口,重寫了clone方法
public class Teacher implements Cloneable{

    private String tname;

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

//Student類重寫clone方法時,調用了Teacher類的clone方法,實現深拷貝
@Override
protected Student clone() throws CloneNotSupportedException {
    Student cloneStudent = (Student) super.clone();
    cloneStudent.setTeacher((Teacher) cloneStudent.getTeacher().clone());
    return cloneStudent;
}
復制代碼

對student對象拷貝并比較兩個對象及對象中的屬性是否相等。

public class cloneObject {
    public static void main(String[] args) throws CloneNotSupportedException {
        Teacher teacher = new Teacher("老師");
        Student student = new Student("學生1",18,teacher);
        System.out.println("clone前的Student對象為:"+student);
        Student cloneStudent = student.clone();
        System.out.println("clone后的Student對象為:"+cloneStudent);
        System.out.println("Student對象與cloneStudent對象是否相等:"+student.equals(cloneStudent));
        System.out.println("student對象和cloneStudent對象中的teacher屬性是否相等:"+student.getTeacher().equals(cloneStudent.getTeacher()));

        //修改student對象中teacher屬性的值,觀察cloneStudent對象中的teacher屬性的值是否會變
        student.getTeacher().setTname("張三老師");
        System.out.println("cloneStudent對象中teacher屬性的值為:"+cloneStudent.getTeacher());
    }
}
復制代碼

打印結果為

clone前的Student對象為:Student{sname='學生1', sage=18, teacher=Teacher{tname='老師'}}
clone后的Student對象為:Student{sname='學生1', sage=18, teacher=Teacher{tname='老師'}}
Student對象與cloneStudent對象是否相等:false
student對象和cloneStudent對象中的teacher屬性是否相等:false
cloneStudent對象中teacher屬性的值為:Teacher{tname='老師'}
復制代碼

打印結果顯示深拷貝后的兩個對象及其中的屬性都不相等。

總結

  1. 拷貝是為了部分或全部復用原對象的屬性,在原對象的基礎上創建一個新的對象。
  2. 淺拷貝是拷貝后兩個對象地址不相等,但兩個對象的部分屬性地址相等,新對象并沒有拷貝所有的屬性,而是復用原對象中的值。
  3. 深拷貝是拷貝后兩個對象不僅地址不相等,兩個對象的所有屬性地址都不相等。


原文鏈接:https://blog.csdn.net/weixin_45985053/article/details/125858305

欄目分類
最近更新