Junky's IT Notebook

          統(tǒng)計(jì)

          留言簿(8)

          積分與排名

          WebSphere Studio

          閱讀排行榜

          評(píng)論排行榜

          Java Clone機(jī)制(轉(zhuǎn))

          1          什么是 Clone ,容易實(shí)現(xiàn)嗎?

          簡(jiǎn)單地說, Clone 就是對(duì)于給定的一個(gè)對(duì)象實(shí)例 o ,得到另一個(gè)對(duì)象實(shí)例 o’ o o’

          型相同( o.getClass() == o’.getClass() ),內(nèi)容相同(對(duì)于 o/o’ 中的字段 f ,如果 f 是基本數(shù)據(jù)類型,則 o.f == o’.f ;如果 f 是對(duì)象引用,則 o.f == o’.f o.f 指向的對(duì)象與 o’.f 指向的對(duì)象的內(nèi)容相同)。通常稱 o’ o 的克隆或副本。

                 直觀上看,似乎很容易為一個(gè)類加上 clone 方法:

          class A {

                 private Type1 field1;

              private Type2 field2;

               …..

              public Object clone() {

                        A a = new A();

                  a.field1 = a.getField1();

                  a.field2 = a.getField2();

                  ……

                  return a;

              }

          }

           

          然而,稍加推敲,就會(huì)發(fā)現(xiàn)這樣的實(shí)現(xiàn)方法有兩個(gè)問題:

          1.         要想某個(gè)類有 clone 功能,必須單獨(dú)為其實(shí)現(xiàn) clone() 函數(shù),函數(shù)實(shí)現(xiàn)代碼與該類定義密切相關(guān)。

          2.         即使基類 A 已有 clone() 函數(shù),其子類 ExtendA 若要具備 clone 功能,則必須 override 其基類 A clone() 函數(shù)。否則,對(duì)類型為 ExtendA 的對(duì)象 ea clone() 方法的調(diào)用,會(huì)執(zhí)行于類 A 中定義的 clone() 方法而返回一個(gè)類型為 A 的對(duì)象,它顯然不是 ea 的克隆。

          2          Java 對(duì) clone 的支持

          萬(wàn)類之初的 Object 類有 clone() 方法:

          protected native Object clone() throws CloneNotSupportedException;

          該方法是 protected 的,顯然是留待被子類 override 的。該方法又是 native 的,必然做了

          與具體平臺(tái)相關(guān)的底層工作。

          事實(shí)上,類 Object clone() 方法首先會(huì)檢查 this.getClass() 是否實(shí)現(xiàn)了 Cloneable 接口。

          Cloneable 只是一個(gè)標(biāo)志接口而已,用來標(biāo)志該類是否有克隆功能。

          public interface Cloneable {

          }

                 如果 this.getClass() 沒有實(shí)現(xiàn) Cloneable 接口, clone() 就會(huì)拋 CloneNotSupportedException 返回。否則就會(huì)創(chuàng)建一個(gè)類型為 this.getClass() 的對(duì)象 other ,并將 this field 的值賦值給 other 的對(duì)應(yīng) field ,然后返回 other

                 如此一來,我們要定義一個(gè)具有 Clone 功能的類就相當(dāng)方便:

          1.         在類的聲明中加入“ implements Cloneable ”,標(biāo)志該類有克隆功能;

          2.         Override Object clone() 方法,在該方法中調(diào)用 super.clone()

          class CloneableClass implements Cloneable {

                 ……

          public Object clone() {

                 try {

                        return super.clone(); // 直接讓 Object.clone() 為我們代勞一切

              } catch (CloneNotSupportedException e) {

                        throw new InternalError();

                 }

          }

          }

           

          3          Shallow Clone Deep Clone

          3.1     Shallow Deep 從何而來

          一個(gè)具有克隆功能的類,如果有可變( Mutable )類類型的字段 field ,如何為其克隆(副

          本)對(duì)象 o’ 中的 field 賦值?

                 方法一、如 Object clone() 方法所實(shí)現(xiàn):設(shè)原始對(duì)象為 o ,其克隆對(duì)象是 o’ ,執(zhí)行 o’.field = o.field 。這樣, o’.field o.field 指向同一個(gè)可變對(duì)象 m o o’ 可能會(huì)相互影響(一個(gè)對(duì)象的狀態(tài)可能會(huì)隨著另一個(gè)對(duì)象的狀態(tài)的改變而改變)。這樣的 Clone 稱為 Shallow Clone 。這也是 Object clone() 方法的實(shí)現(xiàn)方式。

                 方法二、將 o.field 指向的可變對(duì)象 m 克隆,得到 m’ ,將 m’ 的引用賦值給 o’.field 。這樣 o’ o 內(nèi)容相同,且相互之間無(wú)影響(一個(gè)對(duì)象狀態(tài)的改變不會(huì)影響另一個(gè)對(duì)象的狀態(tài))。這樣的 Clone 稱為 Deep Clone

                 Java Collection 類庫(kù)中具體數(shù)據(jù)結(jié)構(gòu)類( ArrayList/LinkedList HashSet/TreeSet HashMap/TreeMap 等)都具有克隆功能,且都是 Shallow Clone ,這樣設(shè)計(jì)是合理的,因?yàn)樗鼈儾恢来娣牌渲械拿總€(gè)數(shù)據(jù)對(duì)象是否也有克隆功能。 System.arrayCopy() 的實(shí)現(xiàn)采用的也是 Shallow Clone

                 Deep Clone 對(duì)于實(shí)現(xiàn)不可變( Immutable )類很有幫助。設(shè)一個(gè)類包含可變類 M 類型的 field ,如何將其設(shè)計(jì)為不可變類呢?先為 M 實(shí)現(xiàn) Deep Clone 功能,然后這樣設(shè)計(jì)類 ImmutableClass

          class ImmutableClass {

                 MutableClass m;

          ImmutableClass(MutableClass m) {

                 this.m = m.clone(); // 將傳入的 m clone 賦值給內(nèi)部 m

          }

          public MutableClass getM() {

              return this.m.clone(); // 將內(nèi)部 m clone 返回給外部

          }

          }

           

                

          3.2     如何實(shí)現(xiàn) Deep Clone

          檢查類有無(wú)可變類類型的字段。如果無(wú),返回 super.clone() 即可;

          如果有,確保包含的可變類本身都實(shí)現(xiàn)了 Deep Clone

          Object o = super.clone(); // 先執(zhí)行淺克隆,確保類型正確和基本類型及非可變類類型字段內(nèi)容正確

          對(duì)于每一個(gè)可變類類型的字段 field

                 o.field = this.getField().clone();

          返回 o

          posted on 2007-05-08 14:02 junky 閱讀(681) 評(píng)論(0)  編輯  收藏 所屬分類: java

          主站蜘蛛池模板: 安溪县| 永新县| 桦南县| 烟台市| 溧阳市| 宣城市| 乡城县| 什邡市| 衡东县| 平乐县| 无锡市| 疏勒县| 资溪县| 原平市| 琼海市| 霍林郭勒市| 康保县| 双江| 福清市| 横山县| 景谷| 富锦市| 滨州市| 雷波县| 金平| 基隆市| 饶阳县| 临海市| 泗阳县| 商丘市| 湘乡市| 涪陵区| 邵武市| 平原县| 南康市| 常州市| 三原县| 安仁县| 社会| 普宁市| 苏尼特右旗|