Java 對象克隆

Java的拷貝可以分為淺拷貝和深拷貝地回。

淺拷貝

淺拷貝示意圖

原變量和拷貝變量引用同一個對象越锈,改變一個變量鎖引用的對象將會對另一個變量產(chǎn)生影響方灾。

        Person original = new Person("johb",20);
        Person copy = origin;
        copy.setAge(21); 

result: original only changed!!!

深拷貝(也叫做克隆)

深拷貝示意圖

如果想創(chuàng)建一個對象的copy议忽,它的初始狀態(tài)和original一樣溉跃,但是以后可以改變各自的狀態(tài)村刨,那就需要使用clone方法
clone是Object的protected方法,Object中的clone方法喊积,由于object類對具體的類對象一無所知烹困,所以只能講各個域進行對應(yīng)的拷貝。如果對象中的數(shù)據(jù)域都是數(shù)值或者基本數(shù)據(jù)類型乾吻,這樣的拷貝沒有問題髓梅,如果對象中包含了子對象拟蜻,那么拷貝的結(jié)果會使得兩個域引用同一個子對象。默認(rèn)的克隆操作是淺拷貝枯饿,沒有克隆包含在對象中的內(nèi)部對象酝锅。
而且,由于clone方法是保護方法奢方,所以用戶不能直接調(diào)用它搔扁,需要在類中重新定義clone方法。

public class Person implements Cloneable{
    public Employee clone() throws CloneNotSupportedException {
        return (Employee )super.clone();
    }
}

上述clone方法沒有在Object.clone()提供的淺拷貝的基礎(chǔ)上新增任何東西蟋字,而只是將這個方法聲明為public稿蹲。為了實現(xiàn)深拷貝,必須克隆所有可變的實例域

public class Person implements Cloneable{
    public Employee clone() throws CloneNotSupportedException {
        Employee cloned = (Employee )super.clone();
        cloned.hireDay = (Data)hireDay.clone;
        return cloned;
    }
}

當(dāng)子對象可變鹊奖,必須重新定義克隆方法苛聘,以便實現(xiàn)克隆子對象的深拷貝

數(shù)組鏈表的拷貝

數(shù)組鏈表也是一種對象,若元素不是基本數(shù)據(jù)類型時忠聚,相當(dāng)于內(nèi)部對象设哗,因此以下幾種方式都是淺拷貝。原始鏈表和拷貝鏈表共享元素两蟀。

幾種淺拷貝

遍歷循環(huán)復(fù)制

        List<Person> srcList = new ArrayList<>();
        srcList.add(new Person("jack", 24));
        srcList.add(new Person("rose", 22));
        List<Person> destList = new ArrayList<>(srcList.size());
        for (Person p : srcList) {
            destList.add(p);
        }

使用List實現(xiàn)類的構(gòu)造方法

        List<Person> srcList = new ArrayList<>();
        srcList.add(new Person("jack", 24));
        srcList.add(new Person("rose", 22));
        List<Person> destList1 = new ArrayList<Person>(srcList);

list.addAll方法

        List<Person> srcList = new ArrayList<>();
        srcList.add(new Person("jack", 24));
        srcList.add(new Person("rose", 22));
        List<Person> destList2 = new ArrayList<Person>();
        destList2.addAll(srcList);
      

System.arraycopy方法

        List<Person> srcList = new ArrayList<>();
        srcList.add(new Person("jack", 24));
        srcList.add(new Person("rose", 22));
        List<Person> destList = new ArrayList<>(srcList.size());
        Person[] srcPersons = srcList.toArray(new Person[0]);
        Person[] destPersons = new Person[srcPersons.length];
        System.arraycopy(srcPersons, 0, destPersons, 0, srcPersons.length);

其實跟進去java代碼网梢,發(fā)現(xiàn)上述三種本質(zhì)都是調(diào)用了System.arraycopy方法
上述拷貝方法,改變了A的元素的屬性赂毯,會改變B战虏。

        srcList.get(0).setName("change!!");
image.png

不過,直接對A進行新增元素等操作欢瞪,并不會影響B(tài)活烙。

        srcList.add(new Person("gga",23));

數(shù)組鏈表的深拷貝

序列化

public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException {  
    ByteArrayOutputStream byteOut = new ByteArrayOutputStream();  
    ObjectOutputStream out = new ObjectOutputStream(byteOut);  
    out.writeObject(src);  
 
    ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());  
    ObjectInputStream in = new ObjectInputStream(byteIn);  
    @SuppressWarnings("unchecked")  
    List<T> dest = (List<T>) in.readObject();  
    return dest;  
}  
 
List<Person> destList=deepCopy(srcList);  //調(diào)用該方法

clone方法

public class A implements Cloneable {   
    public String name[];   
 
    public A(){   
        name=new String[2];   
    }   
 
    public Object clone() {   
        A o = null;   
        try {   
            o = (A) super.clone();   
        } catch (CloneNotSupportedException e) {   
            e.printStackTrace();   
        }   
        return o;   
    }   
}  
for(int i=0;i<n;i+=){
copy.add((A)src.get(i).clone());
}

參考
java List復(fù)制:淺拷貝與深拷貝
java核心技術(shù)卷1 P76 P213

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市遣鼓,隨后出現(xiàn)的幾起案子啸盏,更是在濱河造成了極大的恐慌,老刑警劉巖骑祟,帶你破解...
    沈念sama閱讀 217,084評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件回懦,死亡現(xiàn)場離奇詭異,居然都是意外死亡次企,警方通過查閱死者的電腦和手機怯晕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缸棵,“玉大人舟茶,你說我怎么就攤上這事。” “怎么了吧凉?”我有些...
    開封第一講書人閱讀 163,450評論 0 353
  • 文/不壞的土叔 我叫張陵隧出,是天一觀的道長。 經(jīng)常有香客問我阀捅,道長胀瞪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,322評論 1 293
  • 正文 為了忘掉前任饲鄙,我火速辦了婚禮凄诞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忍级。我一直安慰自己帆谍,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,370評論 6 390
  • 文/花漫 我一把揭開白布颤练。 她就那樣靜靜地躺著既忆,像睡著了一般驱负。 火紅的嫁衣襯著肌膚如雪嗦玖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,274評論 1 300
  • 那天跃脊,我揣著相機與錄音宇挫,去河邊找鬼。 笑死酪术,一個胖子當(dāng)著我的面吹牛器瘪,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播绘雁,決...
    沈念sama閱讀 40,126評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼橡疼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了庐舟?” 一聲冷哼從身側(cè)響起欣除,我...
    開封第一講書人閱讀 38,980評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挪略,沒想到半個月后历帚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,414評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡杠娱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,599評論 3 334
  • 正文 我和宋清朗相戀三年挽牢,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摊求。...
    茶點故事閱讀 39,773評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡禽拔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情睹栖,我是刑警寧澤寥闪,帶...
    沈念sama閱讀 35,470評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站磨淌,受9級特大地震影響疲憋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜梁只,卻給世界環(huán)境...
    茶點故事閱讀 41,080評論 3 327
  • 文/蒙蒙 一缚柳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧搪锣,春花似錦秋忙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,713評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至狗超,卻和暖如春弹澎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背努咐。 一陣腳步聲響...
    開封第一講書人閱讀 32,852評論 1 269
  • 我被黑心中介騙來泰國打工苦蒿, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人渗稍。 一個月前我還...
    沈念sama閱讀 47,865評論 2 370
  • 正文 我出身青樓佩迟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親竿屹。 傳聞我的和親對象是個殘疾皇子报强,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,689評論 2 354