<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
    主站蜘蛛池模板: 永久免费AV无码网站国产| 国产福利免费视频| 久久午夜夜伦鲁鲁片免费无码影视| 亚洲午夜精品一级在线播放放 | 中文字幕乱理片免费完整的| 国产精品99久久免费| 亚洲综合中文字幕无线码| 四虎成年永久免费网站| 91亚洲视频在线观看| 免费人成网站在线观看10分钟| 亚洲系列国产精品制服丝袜第| 777爽死你无码免费看一二区| 亚洲国产精品久久66| 最近2019年免费中文字幕高清 | 男女猛烈无遮掩视频免费软件| 国产又粗又猛又爽又黄的免费视频 | 亚洲精品无码专区在线| 日韩免费毛片视频| 免费看美女午夜大片| 亚洲伊人成无码综合网| 国内精品久久久久影院免费| 久久精品国产精品亚洲毛片| 日本高清在线免费| 亚洲爆乳少妇无码激情| 亚洲?V乱码久久精品蜜桃| 免费无码黄网站在线看| 久久狠狠高潮亚洲精品| 在线观看免费宅男视频| 黄页网站在线观看免费| 久久青青成人亚洲精品| 天天影视色香欲综合免费| 亚洲日韩一中文字暮| 久久精品夜色噜噜亚洲A∨| 日本在线免费观看| 亚洲影视自拍揄拍愉拍| 成人爱做日本视频免费| 99视频在线免费观看| 亚洲人成在线精品| 亚洲av麻豆aⅴ无码电影 | 99亚洲精品卡2卡三卡4卡2卡| 亚洲成网777777国产精品|