天天看點

java深拷貝和淺拷貝

淺拷貝(Shallow Copy):

①對于資料類型是基本資料類型的成員變量,淺拷貝會直接進行值傳遞,也就是将該屬性值複制一份給新的對象。因為是兩份不同的資料,是以對其中一個對象的該成員變量值進行修改,不會影響另一個對象拷貝得到的資料。

②對于資料類型是引用資料類型的成員變量,比如說成員變量是某個數組、某個類的對象等,那麼淺拷貝會進行引用傳遞,也就是隻是将該成員變量的引用值(記憶體位址)複制一份給新的對象。因為實際上兩個對象的該成員變量都指向同一個執行個體。在這種情況下,在一個對象中修改該成員變量會影響到另一個對象的該成員變量值。

淺拷貝的實作方式:

1、通過拷貝構造方法實作淺拷貝

2、通過重寫clone()方法進行淺拷貝:

Object類是類結構的根類,其中有一個方法為protected Object clone() throws ,這個方法就是進行的淺拷貝。有了這個淺拷貝模闆,我們可以通過調用clone()方法來實作對象的淺拷貝。

但是需要注意:1、Object類雖然有這個方法,但是這個方法是受保護的(被protected修飾),是以我們無法直接使用。2、使用clone方法的類必須實作Cloneable接口,否則會抛出異常CloneNotSupportedException。對于這兩點,我們的解決方法是,在要使用clone方法的類中重寫clone()方法,通過super.clone()調用Object類中的原clone方法。

基本資料類型是值傳遞,是以修改值後不會影響另一個對象的該屬性值;

引用資料類型是位址傳遞(引用傳遞),是以修改值後另一個對象的該屬性值會同步被修改。

String類型比較特殊,String類型屬于引用資料類型,不屬于基本資料類型,但是String類型的資料是存放在常量池中的,也就是無法修改的!是以在淺拷貝的時候,如果string屬性變更,是會存在兩個執行個體對象。一個的變更,不會影響另一個

深拷貝的實作方式:

一、通過重寫clone方法來實作深拷貝

與通過重寫clone方法實作淺拷貝的基本思路一樣,隻需要為對象圖的每一層的每一個對象都實作Cloneable接口并重寫clone方法,最後在最頂層的類的重寫的clone方法中調用所有的clone方法即可實作深拷貝。簡單的說就是:每一層的每個對象都進行淺拷貝=深拷貝。

二、通過對象序列化實作深拷貝

雖然層次調用clone方法可以實作深拷貝,但是顯然代碼量實在太大。特别對于屬性數量比較多、層次比較深的類而言,每個類都要重寫clone方法太過繁瑣。

将對象序列化為位元組序列後,預設會将該對象的整個對象圖進行序列化,再通過反序列即可完美地實作深拷貝。

 ​

ps:言簡意赅

淺拷貝:建立一個新對象,然後将目前對象的非靜态字段複制到該新對象,如果字段是值類型的,那麼對該字段執行複制;如果該字段是引用類型的話,則複制引用但不複制引用的對象。是以,原始對象及其副本引用同一個對象。

 深拷貝:建立一個新對象,然後将目前對象的非靜态字段複制到該新對象,無論該字段是值類型的還是引用類型,都複制獨立的一份。當你修改其中一個對象的任何内容時,都不會影響另一個對象的内容。