<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?

    下面的例子包含三個(gè)類UnCloneA,CloneB,CloneMain。CloneB類包含了一個(gè)UnCloneA的實(shí)例和一個(gè)int類型變量,并且重載clone()方法。CloneMain類初始化UnCloneA類的一個(gè)實(shí)例b1,然后調(diào)用clone()方法生成了一個(gè)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
    */
    
    												
    										

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

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





    回頁首


    怎么進(jìn)行深度clone?

    把上面的例子改成深度clone很簡單,需要兩個(gè)改變:一是讓UnCloneA類也實(shí)現(xiàn)和CloneB類一樣的clone功能(實(shí)現(xiàn)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
    */
    
    												
    										

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

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

    還要知道的是除了基本數(shù)據(jù)類型能自動實(shí)現(xiàn)深度clone以外,String對象是一個(gè)例外,它c(diǎn)lone后的表現(xiàn)好象也實(shí)現(xiàn)了深度clone,雖然這只是一個(gè)假象,但卻大大方便了我們的編程。

    posted on 2006-06-12 13:15 Kimi 閱讀(171) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 100部毛片免费全部播放完整| 国产情侣激情在线视频免费看| 国产性爱在线观看亚洲黄色一级片 | 免费日韩在线视频| 亚洲综合一区二区三区四区五区| 57pao一国产成视频永久免费| 久久久久亚洲AV无码网站| 免费在线看污视频| 又大又黄又粗又爽的免费视频| 亚洲精品中文字幕无码A片老| 西西大胆无码视频免费| 国产成人精品日本亚洲18图| 免费国产va视频永久在线观看| 豆国产96在线|亚洲| 亚洲乱码中文论理电影| 一个人免费观看视频在线中文 | 久久久久久久岛国免费播放| 亚洲av无码不卡| 一个人免费日韩不卡视频| 亚洲一级二级三级不卡| 777成影片免费观看| 亚洲国产美女在线观看| 中文字幕无码不卡免费视频| 亚洲精品免费网站| 疯狂做受xxxx高潮视频免费| 大学生a级毛片免费观看| 亚洲国产成人片在线观看| 久久免费视频99| 亚洲激情视频网站| 国产成人免费爽爽爽视频| 亚洲人成网站999久久久综合| 国产成人免费网站在线观看 | 亚洲在成人网在线看| 久久久久久久免费视频| 亚洲 日韩 色 图网站| 国产精品黄页在线播放免费| 一级做a爰片久久毛片免费陪 | 亚洲日韩精品无码AV海量| 四虎影视永久免费视频观看| 一个人看的免费视频www在线高清动漫| 国产亚洲精品无码拍拍拍色欲|