如圖所示
淺拷貝、深拷貝原型模式
深拷貝和淺拷貝的區別(copy的是值還是引用)
1.淺拷貝: 將原對象或原數組的引用直接賦給新對象,新數組,新對象/數組只是原對象的一個引用
2.深拷貝: 創建一個新的對象和數組,將原對象的各項屬性的“值”(數組的所有元素)拷貝過來,是“值”而不是“引用”
java的傳遞類型:java傳遞的話只有值傳遞,不存在引用傳遞。
淺拷貝(Shallow Copy):基本數據類型和引用數據類型。
①對於數據類型是基本數據類型的成員變量,淺拷貝會直接進行值傳遞,也就是將該屬性值複製一份給新的對象。因爲是兩份不同的數據,所以對其中一個對象的該成員變量值進行修改,不會影響另一個對象拷貝得到的數據。
②對於數據類型是引用數據類型的成員變量,比如說成員變量是某個數組、某個類的對象等,那麼淺拷貝會進行引用傳遞,也就是隻是將該成員變量的引用值(內存地址)複製一份給新的對象。因爲實際上兩個對象的該成員變量都指向同一個實例。在這種情況下,在一個對象中修改該成員變量會影響到另一個對象的該成員變量值。
淺拷貝:值類型直接copy一份,修改原有的值對現在的值無影響。
使用原型模式實現的是深拷貝;步驟:1)實現Cloneable接口;2)在clone()方法裏面處理copy邏輯。
String是引用數據類型,但是字符串是不可變類型,所以當做值類型來處理。
基本數據類型淺拷貝與深拷貝等同,引用類型是多個對象公用一塊內存,當一個對象去改變值時,其他也會受影響。
對於引用類型的修改,不能影響到對應的copy對象的值。
淺拷貝與深拷貝的區別。
爲什麼要使用深拷貝?我們希望在改變新的數組或者對象的時候,不改變原數組或對象
引用類型,所以它們是指向同一個內存地址。
Java 中的數據類型分爲基本數據類型和引用數據類型。對於這兩種數據類型,在進行賦值操作、用作方法參數或返回值時,會有值傳遞和引用(地址)傳遞的差別。
根據對對象屬性的拷貝程度(基本數據類和引用類型),會分爲兩種:
淺拷貝 (Shallow Copy); 深拷貝 (Deep Copy)
如何實現淺copy?
實現對象拷貝的類,需要實現 Cloneable 接口,並覆寫 clone() 方法。
implements Cloneable接口,重寫clone()方法,
//直接調用父類的clone()方法 return super.clone();
給Sting類型的變量賦值,就相當於指向了一個新的內存地址,切記。Sting name。
對象拷貝後沒有生成新的對象,二者的對象地址是一樣的;而淺拷貝的對象地址是不一樣的。
淺拷貝會帶來數據安全方面的隱患,把原來的值修改掉。
深拷貝,在拷貝引用類型成員變量時,爲引用類型的數據成員另闢了一個獨立的內存空間,實現真正內容上的拷貝。
深拷貝後,不管是基礎數據類型還是引用類型的成員變量,修改其值都不會相互造成影響。
demo地址:https://www.jianshu.com/p/94dbef2de298
使用自帶的clone方法,需要實現cloneable接口,不然會
Exception in thread "main" java.lang.CloneNotSupportedException
相對於淺拷貝而言,對於引用類型的修改,並不會影響到對應的copy對象的值。每一層的每個對象都進行淺拷貝=深拷貝。
//修改對應的引用對象的值。(修改引用對象的值)
把String當做基本類型來處理。
//淺拷貝
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
//深拷貝
@Override
protected Object clone() throws CloneNotSupportedException {
StudentCopy1 studentCopy1 = (StudentCopy1) super.clone();
SubjectCopy1 subject = studentCopy1.getSubject();
studentCopy1.setSubject((SubjectCopy1) subject.clone());
return studentCopy1;
}
//深拷貝,更方便,三者選其一即可
@Override
protected Object clone() throws CloneNotSupportedException {
StudentCopy1 studentCopy1 = new StudentCopy1();
studentCopy1.setAge(age);
studentCopy1.setName(name);
studentCopy1.setSubject(subject);
return studentCopy1;
}
深拷貝方法具有侷限性,還不如自己創建對象,實現深拷貝。
1、如果多層級需要深拷貝,需要一層層拷貝下去;
2、裏面的類型可能沒有實現Cloneable接口;