<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Kimi's NutShell

    我荒廢的今日,正是昨日殞身之人祈求的明日

    BlogJava 新隨筆 管理
      141 Posts :: 0 Stories :: 75 Comments :: 0 Trackbacks

    影子clone和深度clone

    什么是影子clone?

    下面的例子包含三個類UnCloneA,CloneB,CloneMain。CloneB類包含了一個UnCloneA的實例和一個int類型變量,并且重載clone()方法。CloneMain類初始化UnCloneA類的一個實例b1,然后調用clone()方法生成了一個b1的拷貝b2。最后考察一下b1和b2的輸出:

    												
    														package clone;
    class UnCloneA {
        private int i;
        public UnCloneA(int ii) { i = ii; }
        public void doubleValue() { i *= 2; }
        public String toString() {
            return Integer.toString(i);
        }
    }
    class CloneB implements Cloneable{
        public int aInt;
        public UnCloneA unCA = new UnCloneA(111);
        public Object clone(){
            CloneB o = null;
            try{
                o = (CloneB)super.clone();
            }catch(CloneNotSupportedException e){
                e.printStackTrace();
            }
            return o;
        }
    }
    public class CloneMain {
        public static void main(String[] a){
            CloneB b1 = new CloneB();
            b1.aInt = 11;
            System.out.println("before clone,b1.aInt = "+ b1.aInt);
            System.out.println("before clone,b1.unCA = "+ b1.unCA);
                    
            CloneB b2 = (CloneB)b1.clone();
            b2.aInt = 22;
            b2.unCA.doubleValue();
            System.out.println("=================================");
            System.out.println("after clone,b1.aInt = "+ b1.aInt);
            System.out.println("after clone,b1.unCA = "+ b1.unCA);
            System.out.println("=================================");
            System.out.println("after clone,b2.aInt = "+ b2.aInt);
            System.out.println("after clone,b2.unCA = "+ b2.unCA);
        }
    }
    
    
    /** RUN RESULT:
    before clone,b1.aInt = 11
    before clone,b1.unCA = 111
    =================================
    after clone,b1.aInt = 11
    after clone,b1.unCA = 222
    =================================
    after clone,b2.aInt = 22
    after clone,b2.unCA = 222
    */
    
    												
    										

    輸出的結果說明int類型的變量aInt和UnCloneA的實例對象unCA的clone結果不一致,int類型是真正的被clone了,因為改變了b2中的aInt變量,對b1的aInt沒有產生影響,也就是說,b2.aInt與b1.aInt已經占據了不同的內存空間,b2.aInt是b1.aInt的一個真正拷貝。相反,對b2.unCA的改變同時改變了b1.unCA,很明顯,b2.unCA和b1.unCA是僅僅指向同一個對象的不同引用!從中可以看出,調用Object類中clone()方法產生的效果是:先在內存中開辟一塊和原始對象一樣的空間,然后原樣拷貝原始對象中的內容。對基本數據類型,這樣的操作是沒有問題的,但對非基本類型變量,我們知道它們保存的僅僅是對象的引用,這也導致clone后的非基本類型變量和原始對象中相應的變量指向的是同一個對象。

    大多時候,這種clone的結果往往不是我們所希望的結果,這種clone也被稱為"影子clone"。要想讓b2.unCA指向與b2.unCA不同的對象,而且b2.unCA中還要包含b1.unCA中的信息作為初始信息,就要實現深度clone。





    回頁首


    怎么進行深度clone?

    把上面的例子改成深度clone很簡單,需要兩個改變:一是讓UnCloneA類也實現和CloneB類一樣的clone功能(實現Cloneable接口,重載clone()方法)。二是在CloneB的clone()方法中加入一句o.unCA = (UnCloneA)unCA.clone();

    程序如下:

    												
    														package clone.ext;
    class UnCloneA implements Cloneable{
        private int i;
        public UnCloneA(int ii) { i = ii; }
        public void doubleValue() { i *= 2; }
        public String toString() {
            return Integer.toString(i);
        }
        public Object clone(){
            UnCloneA o = null;
            try{
                o = (UnCloneA)super.clone();
            }catch(CloneNotSupportedException e){
                e.printStackTrace();
            }
            return o;
        }
    }
    class CloneB implements Cloneable{
        public int aInt;
        public UnCloneA unCA = new UnCloneA(111);
        public Object clone(){
            CloneB o = null;
            try{
                o = (CloneB)super.clone();
            }catch(CloneNotSupportedException e){
                e.printStackTrace();
            }
            o.unCA = (UnCloneA)unCA.clone();
            return o;
        }
    }
    public class CloneMain {
        public static void main(String[] a){
            CloneB b1 = new CloneB();
            b1.aInt = 11;
            System.out.println("before clone,b1.aInt = "+ b1.aInt);
            System.out.println("before clone,b1.unCA = "+ b1.unCA);
                    
            CloneB b2 = (CloneB)b1.clone();
            b2.aInt = 22;
            b2.unCA.doubleValue();
            System.out.println("=================================");
            System.out.println("after clone,b1.aInt = "+ b1.aInt);
            System.out.println("after clone,b1.unCA = "+ b1.unCA);
            System.out.println("=================================");
            System.out.println("after clone,b2.aInt = "+ b2.aInt);
            System.out.println("after clone,b2.unCA = "+ b2.unCA);
        }
    }
    
    /** RUN RESULT:
    before clone,b1.aInt = 11
    before clone,b1.unCA = 111
    =================================
    after clone,b1.aInt = 11
    after clone,b1.unCA = 111
    =================================
    after clone,b2.aInt = 22
    after clone,b2.unCA = 222
    */
    
    												
    										

    可以看出,現在b2.unCA的改變對b1.unCA沒有產生影響。此時b1.unCA與b2.unCA指向了兩個不同的UnCloneA實例,而且在CloneB b2 = (CloneB)b1.clone();調用的那一刻b1和b2擁有相同的值,在這里,b1.i = b2.i = 11。

    要知道不是所有的類都能實現深度clone的。例如,如果把上面的CloneB類中的UnCloneA類型變量改成StringBuffer類型,看一下JDK API中關于StringBuffer的說明,StringBuffer沒有重載clone()方法,更為嚴重的是StringBuffer還是一個final類,這也是說我們也不能用繼承的辦法間接實現StringBuffer的clone。如果一個類中包含有StringBuffer類型對象或和StringBuffer相似類的對象,我們有兩種選擇:要么只能實現影子clone,要么就在類的clone()方法中加一句(假設是SringBuffer對象,而且變量名仍是unCA): o.unCA = new StringBuffer(unCA.toString()); //原來的是:o.unCA = (UnCloneA)unCA.clone();

    還要知道的是除了基本數據類型能自動實現深度clone以外,String對象是一個例外,它clone后的表現好象也實現了深度clone,雖然這只是一個假象,但卻大大方便了我們的編程。

    posted on 2006-06-12 13:15 Kimi 閱讀(171) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 亚洲综合校园春色| 亚洲粉嫩美白在线| a级毛片免费全部播放| 亚洲欧洲久久av| 一级做a爰片久久毛片免费陪| 亚洲一区二区三区写真| 九九美女网站免费| 亚洲高清视频免费| 美女视频黄a视频全免费| 国产午夜亚洲精品国产| 日韩高清在线免费看| 美女被吸屁股免费网站| 中文字幕亚洲电影| 一级做a爰全过程免费视频| 亚洲av无码一区二区三区观看| 一级做a爰片久久毛片免费看 | 亚洲小说图片视频| 在线观看AV片永久免费| 亚洲精品成a人在线观看夫| 免费国产综合视频在线看| 99久久婷婷免费国产综合精品| 精品久久久久国产免费| 亚洲黄色免费观看| 免费无码黄十八禁网站在线观看| 亚洲永久精品ww47| 在线观看成人免费视频不卡| 在线a毛片免费视频观看| 国产成人久久精品亚洲小说| 久久久久久久亚洲精品| 91九色视频无限观看免费| 国产精品爱啪在线线免费观看| 啦啦啦www免费视频| 亚洲国产精品日韩av不卡在线| 91av免费观看| 亚洲人成人网站18禁| 亚洲精品tv久久久久| 国产精品白浆在线观看免费| 亚洲妇女水蜜桃av网网站| 亚洲精品无码永久在线观看 | 亚洲三级视频在线观看| 精品剧情v国产在免费线观看|