Java浅克隆与深克隆-clone
文章目錄
- clone
- 淺克隆和深克隆的區(qū)別
- 淺克隆和深克隆的特點
- 另一種參考
- 淺克隆
- 深克隆
- 實現(xiàn)
- 擴展
- 解決多層克隆問題
- 總結(jié)
clone
淺克隆和深克隆的區(qū)別
淺克隆: 對當(dāng)前對象進行克隆,并克隆該對象所包含的8種基本數(shù)據(jù)類型和String類型的屬性(拷貝一份該對象并重新分配內(nèi)存,即產(chǎn)生了新的對象)。但如果被克隆的對象中包含除了8種數(shù)據(jù)類型和String類型外的其他類型的屬性,淺克隆并不會克隆這些屬性(即不會為這些屬性分配內(nèi)存,而是引用原來對象中的屬性)
深克隆: 深克隆是在淺克隆的基礎(chǔ)上,遞歸地克隆除了8種基本類型和String類型之外的屬性(即為這些屬性重新分配內(nèi)存而非引用原來對象中的屬性)
淺克隆和深克隆的特點
另一種參考
淺克隆
在淺克隆中,如果原型對象的成員變量是值類型,將復(fù)制一份給克隆對象;如果原型對象的成員變量是引用類型,則將引用對象的地址復(fù)制一份給克隆對象,也就是說克隆得到的對象和原型對象的成員變量指向相同的內(nèi)存地址。
簡單來說,在淺克隆中,當(dāng)對象被復(fù)制時,只是復(fù)制它本身和其中包含的值類型的成員變量,而引用類型的成員變量并沒有復(fù)制。
在Java中,通過覆蓋Object類的 clone( )方法可以實現(xiàn)淺克隆
深克隆
在深克隆中,無論原型對象的成員變量是值類型還是引用類型,都將復(fù)制一份給克隆對象,深克隆將原型對象的所有引用對象也復(fù)制一份給克隆對象。
簡單來說,在深克隆中,除了對象本身被復(fù)制外,對象所包含的所有成員變量也將復(fù)制。
實現(xiàn)
Java中實現(xiàn)深克隆,可以通過覆蓋 Object類的 clone( )方法實現(xiàn),也可以通過序列化(Serialization)等方式實現(xiàn)
(如果引用類型里面還包含很多引用類型,或者內(nèi)層引用類型的類里面又包含引用類型,使用clone方法會很麻煩。這時我們可以用序列化的方式來實現(xiàn)對象的深克隆)
序列化就是將對象寫到流的過程,寫到流中的對象是原有對象的一個拷貝,而原有對象仍然存在于內(nèi)存中。通過序列化實現(xiàn)的拷貝不僅可以復(fù)制對象本身,而且可以復(fù)制其引用的成員變量。因此通過序列化將對象寫到一個流中,再從流中將其讀出來,可以實現(xiàn)深克隆。需要注意的是能夠?qū)崿F(xiàn)序列化的對象,其類必須實現(xiàn) Serializable接口,否則無法實現(xiàn)序列化操作。
擴展
Java語言提供的 Cloneable接口和 Serializable接口的代碼非常簡單,它們都是空接口。這種接口也稱為標(biāo)識接口,標(biāo)識接口中沒有任何方法的定義,其作用是告訴 JRE這些接口的實現(xiàn)類是否具有某個功能,如是否支持克隆、是否支持序列化等。
解決多層克隆問題
如果引用類型里面還包含很多引用類型,或者內(nèi)層引用類型的類里面又包含引用類型,使用clone方法就會很麻煩。這時我們可以用序列化的方式來實現(xiàn)對象的深克隆。
public class Outer implements Serializable{private static final long serialVersionUID = 369285298572941L; //最好是顯式聲明IDpublic Inner inner;//Discription:[深度復(fù)制方法,需要對象及對象所有的對象屬性都實現(xiàn)序列化] public Outer myclone() {Outer outer = null;try {// 將該對象序列化成流,因為寫在流里的是對象的一個拷貝,而原對象仍然存在于JVM里面。所以利用這個特性可以實現(xiàn)對象的深拷貝ByteArrayOutputStream baos = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(baos);oos.writeObject(this);// 將流序列化成對象ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());ObjectInputStream ois = new ObjectInputStream(bais);outer = (Outer) ois.readObject();} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}return outer;} }Inner也必須實現(xiàn)Serializable,否則無法序列化:
public class Inner implements Serializable{private static final long serialVersionUID = 872390113109L; //最好是顯式聲明IDpublic String name = "";public Inner(String name) {this.name = name;}@Overridepublic String toString() {return "Inner的name值為:" + name;} }這樣也能使兩個對象在內(nèi)存空間內(nèi)完全獨立存在,互不影響對方的值。
總結(jié)
實現(xiàn)對象的克隆有兩種方式:
注意:
基于序列化和反序列化實現(xiàn)的克隆不僅僅是深度克隆,更重要的是通過泛型限定,可以檢查出要克隆的對象是否支持序列化,這項檢查是編譯器完成的,不是在運行時拋出異常。這種方案明顯優(yōu)于使用Object類的clone方法克隆對象。讓問題在編譯的時候暴露出來總是優(yōu)于把問題留到運行時。
TODO
總結(jié)
以上是生活随笔為你收集整理的Java浅克隆与深克隆-clone的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用容联云通讯实现手机验证码注册
- 下一篇: 雷军:四年前我唯一的错,就是把小米少估了