天天看點

java 淺複制和深複制的實作

在Thing類中增加一個私有變量arrayLis,類型為ArrayList,然後通過setValue和getValue分别進行設定和取值,我們來看場景類是如何拷貝的,如代碼清單13-11所示。

代碼清13-11 淺拷貝測試

結果會是什麼?

[張三, 李四] 

為什麼?

怎麼會這樣呢?怎麼會有李四呢?讓我來給你解釋,是因為Java做了一個偷懶的拷貝動作,Object類提供的方法clone隻是拷貝本對象,其對象内部的數組、引用對象等都不拷貝,還是指向原生對象的内部元素位址,這種拷貝就叫做淺拷貝,确實是非常淺,兩個對象共享了一個私有變量,你改我改大家都能改,是一種非常不安全的方式,在實際項目中使用還是比較少的(當然,這是也是一種"危機"環境的一種救命方式)。你可能會比較奇怪,為什麼在Mail那個類中就可以使用String類型,而不會産生由淺拷貝帶來的問題呢?内部的數組和引用對象才不拷貝,其他的原始類型比如int,long,String(Java就希望你把String認為是基本類型,String是沒有clone方法的)等都會被拷貝的。

注意  使用clone方法拷貝時,滿足兩個條件的對象才不會被拷貝:一是類的成員變量,而不是方法内的變量;二是必須是一個對象,而不是一個原始類型

淺拷貝是有風險的,那怎麼才能深入的拷貝呢?我們修改一下程式就可以深拷貝,如代碼清單13-12所示。

僅僅增加了黑體部分,對私有的類變量進行獨立的拷貝。Client類沒有任何改變,運作結果如下所示。

[張三] 

該方法就實作了完全的拷貝,兩個對象之間沒有任何的瓜葛了,你修改你的,我修改我的,不互相影響,這種拷貝就叫做深拷貝,深拷貝還有一種實作方式就是通過自己寫二進制流來操作對象,然後實作對象的深拷貝,這個大家有時間自己實作一下。

注意  深拷貝和淺拷貝建議不要混合使用,特别是是在涉及到類的繼承,父類有多個引用的情況就非常的複雜,建議的方案是深拷貝和淺拷貝分開實作。