Java Clone 學(xué)習(xí)

Java Clone 學(xué)習(xí)

原文地址:詳解Java中的clone方法

通常在Java中我們通過new關(guān)鍵字創(chuàng)建對象泰涂,代碼如下:

Human human = new Human();
Human human2 = human;
System.out.println("human is :" + human);
System.out.println("human2 is :" + human2);

打印如下:

human is :TestClone$Human@6d06d69c

human2 is :TestClone$Human@6d06d69c

從結(jié)果看出human2和human指向了同一對象虐呻,從這行代碼頁印證了引用即是Java種的指針這一說法藻三。

Java中創(chuàng)建對象的方法有很多垫竞,常見的有:

  • new 使用new關(guān)鍵字首先為新對象創(chuàng)建內(nèi)存透揣,然后使用構(gòu)造函數(shù)為新對象的各個(gè)Field初始化
  • clone 首先為新對象創(chuàng)建內(nèi)存疏哗,然后使用舊的對象的值填充新的對象的各個(gè)Field
  • readobject 首先為新對象創(chuàng)建內(nèi)存疲迂,從流中讀取數(shù)據(jù)若未,并填充新對象的各個(gè)Field

Clone 方法

Clone 定義在Object類中的保護(hù)方法朱嘴,一個(gè)類如果要支持Clone,需要按照下面的兩個(gè)步驟編寫代碼粗合。

  • 重寫Clone方法
  • 實(shí)現(xiàn)Cloneable接口 - Cloneable是一個(gè)標(biāo)記接口萍嬉,實(shí)現(xiàn)這個(gè)接口只需要在頂一類是聲明即可,如果類未實(shí)現(xiàn)Cloneable接口隙疚,調(diào)用其Clone方法會(huì)拋出CloneNotSupportedException

一個(gè)例子:

static class Human implements Cloneable {
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public static void main(String[] args) {
    Human human1 = new Human();
    System.out.println("human is :" + human1);
    try {
        Human human2 = (Human) human1.clone();
        System.out.println("human2 is :" + human2);
    } catch (CloneNotSupportedException e) {
        System.out.println("human CloneNotSupportedException");
    }
}

運(yùn)行結(jié)果為:

human is :TestClone$Human@6d06d69c

human2 is :TestClone$Human@7852e922

從運(yùn)行結(jié)果看壤追,Clone方法創(chuàng)建了新的對象。

深復(fù)制和淺復(fù)制

淺復(fù)制

淺復(fù)制是指為新的對象創(chuàng)建內(nèi)存甚淡,并使用舊的對象的中的引用的值填充新的對象中引用的值大诸,觀察如下代碼:

static class Human implements Cloneable {
    public Head mHead;

    public Human(Head head) {
        mHead = head;
    }

    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public static void main(String[] args) {
    Human human1 = new Human(new Head());
    try {
        Human human2 = (Human) human1.clone();
        System.out.println("human1 is :" + human1);
        System.out.println("human2 is :" + human2);
        System.out.println("human1 head is :" + human1.mHead);
        System.out.println("human2 head is :" + human2.mHead);
    } catch (CloneNotSupportedException e) {
        System.out.println("human CloneNotSupportedException");
    }
}

運(yùn)行結(jié)果:

human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@4e25154f

從運(yùn)行結(jié)果看,Object類中Clone方法的實(shí)現(xiàn)為淺復(fù)制

深復(fù)制

深復(fù)制是指贯卦,為新的對象申請內(nèi)存资柔,并未其中的每個(gè)引用申請內(nèi)存。將上述的代碼改造如下:

static class Head implements Cloneable {
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

static class Human implements Cloneable {
    public Head mHead;

    public Human(Head head) {
        mHead = head;
    }

    public Object clone() throws CloneNotSupportedException {
        Human human = (Human) super.clone();
        human.mHead = (Head) mHead.clone();
        return human;
    }
}

public static void main(String[] args) {
    Human human1 = new Human(new Head());
    try {
        Human human2 = (Human) human1.clone();
        System.out.println("human1 is :" + human1);
        System.out.println("human2 is :" + human2);
        System.out.println("human1 head is :" + human1.mHead);
        System.out.println("human2 head is :" + human2.mHead);
    } catch (CloneNotSupportedException e) {
        System.out.println("human CloneNotSupportedException");
    }

}

結(jié)果如下:

human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e

從結(jié)果看human和head都指向了新的對象(內(nèi)存)撵割。

繼續(xù)改造上述代碼:

static class Face {

}

static class Head implements Cloneable {
    Face mFace;

    public Head() {
        mFace = new Face();
    }

    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

static class Human implements Cloneable {
    public Head mHead;

    public Human(Head head) {
        mHead = head;
    }

    public Object clone() throws CloneNotSupportedException {
        Human human = (Human) super.clone();
        human.mHead = (Head) mHead.clone();
        return human;
    }
}

public static void main(String[] args) {
    Human human1 = new Human(new Head());
    try {
        Human human2 = (Human) human1.clone();
        System.out.println("human1 is :" + human1);
        System.out.println("human2 is :" + human2);
        System.out.println("human1 head is :" + human1.mHead);
        System.out.println("human2 head is :" + human2.mHead);
        System.out.println("human1 face is :" + human1.mHead.mFace);
        System.out.println("human2 face is :" + human2.mHead.mFace);
    } catch (CloneNotSupportedException e) {
        System.out.println("human CloneNotSupportedException");
    }
}

運(yùn)行結(jié)果如下:

human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e
human1 face is :TestClone$Face@5c647e05
human2 face is :TestClone$Face@5c647e05
從結(jié)果看face又指向了相同對象(引用)贿堰,為了完成徹底的深復(fù)制,需要對Face類和Head類做如下改造:

static class Face implements Cloneable {
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

static class Head implements Cloneable {
    Face mFace;

    public Head() {
        mFace = new Face();
    }

    protected Object clone() throws CloneNotSupportedException {
        Head head = (Head) super.clone();
        head.mFace = (Face) mFace.clone();
        return head;
    }
}

結(jié)果如下:

human1 is :TestClone$Human@6d06d69c
human2 is :TestClone$Human@7852e922
human1 head is :TestClone$Head@4e25154f
human2 head is :TestClone$Head@70dea4e
human1 face is :TestClone$Face@5c647e05
human2 face is :TestClone$Face@33909752

結(jié)論

  1. Object類提供了Clone方法用于復(fù)制對象,
  2. 一個(gè)類如果要支持Clone啡彬,需要重寫Clone方法羹与,并實(shí)現(xiàn)Cloneable接口
  3. Object類的Clone實(shí)現(xiàn)為淺復(fù)制
  4. 為了達(dá)到深復(fù)制,對象的引用庶灿,以及其引用的引用(依次類推)都需要實(shí)現(xiàn)深復(fù)制
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纵搁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子往踢,更是在濱河造成了極大的恐慌腾誉,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異利职,居然都是意外死亡趣效,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門猪贪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跷敬,“玉大人,你說我怎么就攤上這事热押∥骺” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵楞黄,是天一觀的道長池凄。 經(jīng)常有香客問我,道長鬼廓,這世上最難降的妖魔是什么肿仑? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮碎税,結(jié)果婚禮上尤慰,老公的妹妹穿的比我還像新娘。我一直安慰自己雷蹂,他們只是感情好伟端,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著匪煌,像睡著了一般责蝠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上萎庭,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天霜医,我揣著相機(jī)與錄音,去河邊找鬼驳规。 笑死肴敛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吗购。 我是一名探鬼主播医男,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼捻勉!你這毒婦竟也來了镀梭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對情侶失蹤踱启,失蹤者是張志新(化名)和其女友劉穎报账,沒想到半個(gè)月后撒强,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笙什,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胚想。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琐凭。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖浊服,靈堂內(nèi)的尸體忽然破棺而出统屈,到底是詐尸還是另有隱情,我是刑警寧澤牙躺,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布愁憔,位于F島的核電站,受9級(jí)特大地震影響孽拷,放射性物質(zhì)發(fā)生泄漏吨掌。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一脓恕、第九天 我趴在偏房一處隱蔽的房頂上張望膜宋。 院中可真熱鬧,春花似錦炼幔、人聲如沸秋茫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肛著。三九已至,卻和暖如春跺讯,著一層夾襖步出監(jiān)牢的瞬間枢贿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國打工抬吟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留萨咕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓火本,卻偏偏與公主長得像危队,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子钙畔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容