亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

java中的深淺克隆

2019-11-14 23:40:16
字體:
來源:轉載
供稿:網友
java中的深淺克隆

假設有一個對象object,在某處又需要一個跟object一樣的實例object2,強調的是object和object2是兩個獨立的實例,只是在開始的時候,他們是具有相同狀態的(屬性字段的值都相同)。遇到這種情況的做法一般是,重新new一個對象object2,將object的字段值賦予object2,即:object2=object; 這樣的話兩個引用仍然指向的是同一個對象,不是兩個對象。

克隆方法clone()

Java中跟克隆有關的兩個類分別是Cloneable接口和Object類中的clone方法,通過兩者的協作來實現克隆。

首先來看看Object的clone()源代碼:

    /**     * Creates and returns a copy of this {@code Object}. The default     * implementation returns a so-called "shallow" copy: It creates a new     * instance of the same class and then copies the field values (including     * object references) from this instance to the new instance. A "deep" copy,     * in contrast, would also recursively clone nested objects. A subclass that     * needs to implement this kind of cloning should call {@code super.clone()}     * to create the new instance and then create deep copies of the nested,     * mutable objects.     *     * @return a copy of this object.     * @throws CloneNotSupportedException     *             if this object's class does not implement the {@code     *             Cloneable} interface.     */    PRotected Object clone() throws CloneNotSupportedException {        if (!(this instanceof Cloneable)) {            throw new CloneNotSupportedException("Class doesn't implement Cloneable");        }        return internalClone((Cloneable) this);    }    /*     * Native helper method for cloning.     */    private native Object internalClone(Cloneable o);

首先看一下java api doc中關于Cloneable接口和Object類中的clone方法的描述:

java.lang.Cloneable 接口(以下源引JavaTM 2 Platform Standard Ed. 5.0 API DOC)

此類實現了 Cloneable 接口,以指示 Object.clone() 方法可以合法地對該類實例進行按字段復制。 如果在沒有實現 Cloneable 接口的實例上調用 Object 的 clone 方法,則會導致拋出 CloneNotSupportedException異常。

按照慣例,實現此接口的類應該使用公共方法重寫 Object.clone(它是受保護的)。請參閱 Object.clone(),以獲得有關重寫此方法的詳細信息。

注意,此接口不包含 clone 方法。因此,因為某個對象實現了此接口就克隆它是不可能的。即使 clone 方法是反射性調用的,也無法保證它將獲得成功。

Cloneable接口沒有任何方法,僅是個標志接口(tagging interface),若要具有克隆能力,實現Cloneable接口的類必須重寫從Object繼承來的clone方法,并調用Object的clone方法(見下面Object#clone的定義),重寫后的方法應為public 的。

clone方法首先會判對象是否實現了Cloneable接口,若無則拋出CloneNotSupportedException, 最后會調用internalClone. intervalClone是一個native方法,一般來說native方法的執行效率高于非native方法。

當某個類要復寫clone方法時,要繼承Cloneable接口。通常的克隆對象都是通過super.clone()方法來克隆對象。

淺克隆(shadow clone)

克隆就是復制一個對象的復本,若只需要復制對象的字段值(對于基本數據類型,如:int,long,float等,則復制值;對于復合數據類型僅復制該字段值,如數組變量則復制地址,對于對象變量則復制對象的reference。

舉個例子:

public class ShadowClone implements Cloneable{           private int a;   // 基本類型    private int[] b; // 非基本類型    // 重寫Object.clone()方法,并把protected改為public    @Override    public Object clone(){        ShadowClone sc = null;        try        {            sc = (ShadowClone) super.clone();        } catch (CloneNotSupportedException e){            e.printStackTrace();        }        return sc;    }    public int getA()    {        return a;    }    public void setA(int a)    {        this.a = a;    }    public int[] getB() {      return b;    }    public void setB(int[] b) {      this.b = b;    }  }

測試代碼如下:

public class Test{    public static void main(String[] args) throws CloneNotSupportedException{        ShadowClone c1 = new ShadowClone();        //對c1賦值        c1.setA(100) ;        c1.setB(new int[]{1000}) ;                System.out.println("克隆前c1:  a="+c1.getA()+" b="+c1.getB()[0]);        //克隆出對象c2,并對c2的屬性A,B,C進行修改        ShadowClone c2 = (ShadowClone) c1.clone();        //對c2進行修改        c2.setA(50) ;        int []a = c2.getB() ;        a[0]=5 ;        c2.setB(a);        System.out.println("克隆前c1:  a="+c1.getA()+" b="+c1.getB()[0]);        System.out.println("克隆后c2:  a="+c2.getA()+ " b[0]="+c2.getB()[0]);    }}

運行結果:

克隆前c1: a=100 b=1000克隆前c1: a=100 b=5克隆后c2: a=50 b[0]=5

c1和c2的對象模型:

可以看出,基本類型可以使用淺克隆,而對于引用類型,由于引用的是內容相同,所以改變c2實例對象中的屬性就會影響到c1。所以引用類型需要使用深克隆。另外,在開發一個不可變類的時候,如果這個不可變類中成員有引用類型,則就需要通過深克隆來達到不可變的目的。

深克隆(deep clone)

深克隆與淺克隆的區別在于對復合數據類型的復制。若對象中的某個字段為復合類型,在克隆對象的時候,需要為該字段重新創建一個對象。

再舉一個例子:

public class DeepClone implements Cloneable {    private int a;   // 基本類型    private int[] b; // 非基本類型    // 重寫Object.clone()方法,并把protected改為public    @Override    public Object clone(){        DeepClone sc = null;        try        {            sc = (DeepClone) super.clone();            int[] t = sc.getB();            int[] b1 = new int[t.length];            for (int i = 0; i < b1.length; i++) {                b1[i] = t[i];            }            sc.setB(b1);        } catch (CloneNotSupportedException e){            e.printStackTrace();        }        return sc;    }    public int getA()    {        return a;    }    public void setA(int a)    {        this.a = a;    }    public int[] getB() {        return b;    }    public void setB(int[] b) {        this.b = b;    }}

運行結果:

克隆前c1: a=100 b=1000

克隆前c1: a=100 b=1000

克隆后c2: a=50 b[0]=5

對象模型:

使用序列化實現深克隆
public class DeepClone implements Serializable{    private int a;    private int[] b;    public int getA() {        return a;    }    public void setA(int a)    {        this.a = a;    }    public int[] getB() {        return b;    }    public void setB(int[] b) {        this.b = b;    }  }

然后編寫測試類:

package test2;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;public class Test2{    public static void main(String[] args) throws CloneNotSupportedException{        Test2 t = new Test2();        DeepClone dc1 = new DeepClone();        // 對dc1賦值        dc1.setA(100);        dc1.setB(new int[] { 1000 });        System.out.println("克隆前dc1: a=" + dc1.getA()+"b[0]=" + dc1.getB()[0]);        DeepClone dc2 = (DeepClone) t.deepClone(dc1);        // 對c2進行修改        dc2.setA(50);        int[] a = dc2.getB();        a[0] = 500;        System.out.println("克隆后dc1: a=" + dc1.getA()+"b[0]=" + dc1.getB()[0]);        System.out.println("克隆后dc2: a=" + dc2.getA()+"b[0]=" + dc2.getB()[0]);    }    // 用序列化與反序列化實現深克隆    public Object deepClone(Object src){        Object o = null;        try{            if (src != null){                ByteArrayOutputStream baos = new ByteArrayOutputStream();                ObjectOutputStream oos = new ObjectOutputStream(baos);                oos.writeObject(src);                oos.close();                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());                ObjectInputStream ois = new ObjectInputStream(bais);                o = ois.readObject();                ois.close();            }        } catch (IOException e){            e.printStackTrace();        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        return o;    }}

運行后的結果如下:

克隆前dc1: a=100 b[0]=1000

克隆后dc1: a=100 b[0]=1000

克隆后dc2: a=50 b[0]=500可以看到,兩個引用所指向的對象在堆中相互獨立,互不干擾,這樣就實現了深度克隆。

總結:

1、克隆方法用于創建對象的拷貝,為了使用clone方法,類必須實現java.lang.Cloneable接口重寫protected方法clone,如果沒有實現Clonebale接口會拋出CloneNotSupportedException.

2、在克隆java對象的時候不會調用構造器

3、java提供一種叫淺拷貝(shallow copy)的默認方式實現clone,創建好對象的副本后然后通過賦值拷貝內容,意味著如果你的類包含引用類型,那么原始對象和克隆都將指向相同的引用內容,這是很危險的,因為發生在可變的字段上任何改變將反應到他們所引用的共同內容上。為了避免這種情況,需要對引用的內容進行深度克隆。

4、按照約定,實例的克隆應該通過調用super.clone()獲取,這樣有助克隆對象的不變性。如:clone!=original和clone.getClass()==original.getClass(),盡管這些不是必須的

參考資料

http://www.49028c.com/shishm/archive/2011/10/10/2205743.html

http://blog.csdn.net/bigconvience/article/details/25025561


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩欧美aⅴ综合网站发布| 精品二区三区线观看| 欧美中文在线字幕| 亚洲视频日韩精品| 国产精品丝袜久久久久久高清| 欧美视频在线观看 亚洲欧| 日韩不卡在线观看| 欧美精品情趣视频| 4388成人网| 亚洲电影免费观看高清完整版在线观看| 国产视频999| 久久久久久久999精品视频| 日本一本a高清免费不卡| 91av免费观看91av精品在线| 欧美在线视频免费| 久久久久久久久久国产| 在线观看精品国产视频| 狠狠色狠色综合曰曰| 日韩精品中文字幕有码专区| 91理论片午午论夜理片久久| 成人中文字幕+乱码+中文字幕| 久久精品视频免费播放| 国产欧美va欧美va香蕉在线| 精品日韩视频在线观看| 日韩中文字幕网| 欧美国产日韩免费| 欧美多人爱爱视频网站| 亚洲欧美在线磁力| 国内精品一区二区三区| 欧美一区二区影院| 久久久久久这里只有精品| 亚洲一区美女视频在线观看免费| 久久久久久成人精品| 成人亚洲欧美一区二区三区| 欧美性猛交xxxx黑人猛交| 国产精品国产亚洲伊人久久| 亚洲国产精品悠悠久久琪琪| 国产午夜精品一区理论片飘花| 日韩中文字幕网站| 97超碰国产精品女人人人爽| 精品久久香蕉国产线看观看gif| 91成人在线视频| 久久久久久久影院| 久久伊人91精品综合网站| 国产欧美精品在线| 91精品国产综合久久久久久蜜臀| 欧美在线一区二区三区四| 欧美老女人xx| 日韩电影免费在线观看中文字幕| 国产精品成人一区二区| 成人免费福利视频| 欧美电影免费看| 亚洲精品免费网站| 日韩一区二区三区xxxx| 亚洲国产成人精品女人久久久| 亚洲精品电影在线观看| 日韩欧美在线视频日韩欧美在线视频| 国产精品成av人在线视午夜片| 国产一区二区激情| 精品国产欧美成人夜夜嗨| 亚洲激情第一页| 88国产精品欧美一区二区三区| 成人观看高清在线观看免费| 国产精品久久久久77777| 国产精品美腿一区在线看| 中文字幕国产精品| 亚洲精品日产aⅴ| 成年人精品视频| 日韩有码在线播放| 成人a在线观看| 国产成人自拍视频在线观看| 欧美日产国产成人免费图片| 日本成人在线视频网址| 精品亚洲一区二区| 国产成人一区二区三区小说| 亚洲欧美日韩一区二区三区在线| 麻豆乱码国产一区二区三区| 欧美精品久久久久久久久久| 在线免费看av不卡| 欧美丰满少妇xxxx| 日韩精品欧美国产精品忘忧草| 欧美激情视频在线| 欧美人成在线视频| 精品国产一区二区三区四区在线观看| 亚洲tv在线观看| 黑人极品videos精品欧美裸| 亚洲性视频网址| 精品伊人久久97| 中文字幕亚洲图片| 久久久久久亚洲精品中文字幕| 国产91精品久久久久久| 海角国产乱辈乱精品视频| 777精品视频| 国产精品免费小视频| 成人av在线亚洲| 亚洲精品av在线播放| 国产精品视频专区| 国产精品大片wwwwww| 久久久国产一区| 国产欧美日韩中文字幕| 国产精品久久久久久久久久久不卡| 在线国产精品播放| xxx成人少妇69| 黑人狂躁日本妞一区二区三区| 国产精品久久色| 日韩最新av在线| 免费91麻豆精品国产自产在线观看| 久久久久国色av免费观看性色| 久久亚洲综合国产精品99麻豆精品福利| 国产成人aa精品一区在线播放| 国产精品盗摄久久久| 一区二区三区国产在线观看| 欧美成人在线免费| 久久久久久久999精品视频| 97免费视频在线播放| 在线观看久久av| 日韩欧美精品中文字幕| 国产日韩欧美在线| 日韩av电影在线免费播放| 欧美综合一区第一页| 亚洲一区二区中文字幕| 亚洲级视频在线观看免费1级| 成人自拍性视频| 欧美日韩国产999| 亚洲欧美精品在线| 日本欧美在线视频| 日韩福利在线播放| 亚洲视频国产视频| 国产美女被下药99| 最新日韩中文字幕| 欧美巨乳美女视频| 久久亚洲成人精品| 欧美国产乱视频| 国产精品普通话| 亚洲最新在线视频| 亚洲精品小视频| 国产精品91久久久久久| 亚洲美女又黄又爽在线观看| 国产精品视频久久久久| 色一情一乱一区二区| 亚洲精品97久久| 欧美老女人性生活| 欧美在线亚洲一区| 国产精品揄拍一区二区| 亚洲www视频| 日韩欧美在线字幕| 亚洲毛片在线观看.| 国产男人精品视频| 精品视频一区在线视频| 久久久久国色av免费观看性色| 久久精品视频va| 国产精品视频区1| 国产精品免费网站| 午夜精品久久久久久久99热浪潮| 亚洲天堂网站在线观看视频| 久久精品国产一区二区电影| 最近2019中文字幕一页二页| 国产一区二区黄| 精品国产福利视频| 97在线免费观看视频| 国外日韩电影在线观看| 久久偷看各类女兵18女厕嘘嘘| 尤物九九久久国产精品的分类| 亚洲精品久久久久久久久|