Java中深拷貝與淺拷貝理解


在《Java編程思想》第16章數組部分,提到了System.arraycopy()對基本類型數組與對象數組的淺復制(參考P451),因此具體的來學習一下深拷貝與淺拷貝。

 

淺拷貝(Shallow Copy):

1. 對於基本數據類型,淺拷貝會直接進行值傳遞,也就是將該屬性值復制一份給新的對象。因為是兩份不同的數據,所以對其中一個對象的該成員變量值進行修改,不會影響另一個對象拷貝得到的數據。

2. 對於引用類型,比如說成員變量是某個數組、某個類的對象等,那么淺拷貝會進行引用傳遞,也就是只是將該成員變量的引用值(內存地址)復制一份給新的對象。因為實際上兩個對象的該成員變量都指向同一個實例。在這種情況下,在一個對象中修改該成員變量會影響到另一個對象的該成員變量值。

 

深拷貝(deep copy):

1. 對於深拷貝來說,不僅要復制對象的所有基本數據類型,還要為所有引用類型的成員變量申請存儲空間,並復制每個引用類型所引用的對象,直到該對象可達的所有對象。

 

(一)淺拷貝的實現方法

1. 引用賦值;

 

2. 重寫clone方法:

Object類是類結構的根類,其中有一個進行淺拷貝的方法:

protected Object clone() throws CloneNotSupportedException

有了這個淺拷貝模板,我們可以通過調用clone()方法來實現對象的淺拷貝。但是需要注意:

i) Object類雖然有這個方法,但是這個方法是受保護的(被protected修飾),無法直接使用。因此使用clone方法的類必須實現Cloneable接口,否則會拋出異常CloneNotSupportedException。

ii) 使用的基本形式:

class A implements Cloneable {
    public Object clone() {
        Object obj = null;
        try {
            obj = super.clone();
        } catch (CloneNotSupportedException e) {
        }
        return obj;
    }
}
這一奇怪的用法《Java編程思想》的作者嘗試給出了解釋:Java剛開始作為一種驅動硬件的語言出現,那時候Object類有個方法是public Object clone();隨着Java被用到網絡編程中,clone方法的安全性受到質疑,因此設計者將public類型的clone方法修改為protected類型;但即便這樣,仍然有安全問題,因為子類可能濫用父類的clone方法,因為它是protected類型的。為此,Java設計者又設計了一個Cloneable接口,當子類執行super.clone()語句時,會先核對執行該語句的子類對象是否實現了Cloneabe接口,以便確認開發者需要打開該子類的克隆功能,這就能最大程度的保證安全性。

 

(二)深拷貝的實習方法

1. 對每一個引用對象重寫clone方法

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

 

2. 通過對象序列化實現深拷貝(推薦使用)

將對象序列化為字節序列時,默認會將該對象的引用對象進行序列化,再通過反序列即可完美地實現深拷貝。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM