<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    JAVA 對(duì)象拷貝

    為什么需要有對(duì)象拷貝?

    對(duì)象拷貝相對(duì)的自然是引用拷貝。java初學(xué)者經(jīng)常會(huì)問(wèn),我這個(gè)方法要改變一個(gè)對(duì)象的屬性,可以把參數(shù)傳進(jìn)去了,為什么沒有改變了?

    ——基本數(shù)據(jù)類型傳值,而對(duì)象傳引用或引用的拷貝。

    而有時(shí)候我們要獲取到一個(gè)當(dāng)前狀態(tài)的對(duì)象復(fù)制品,他們是兩個(gè)獨(dú)立對(duì)象。不再是引用或者引用拷貝(實(shí)質(zhì)都是指向?qū)ο蟊旧恚>褪钦f(shuō)a是b的拷貝,b發(fā)生變化的時(shí)候,不要影響a。


    對(duì)象拷貝有淺拷貝和深度拷貝兩種。

    1)淺拷貝

    淺拷貝是指對(duì)象中基本數(shù)據(jù)類型得到拷貝,而引用數(shù)據(jù)類型并未拷貝。
    提到拷貝自然和clone聯(lián)系起來(lái)了,所有具有clone功能的類都有一個(gè)特性,那就是它直接或間接地實(shí)現(xiàn)了Cloneable接口。
    否則,我們?cè)趪L試調(diào)用clone()方法時(shí),將會(huì)觸發(fā)CloneNotSupportedException異常。
    eg:

    ?1 public ? class ?DOG? implements ?Cloneable
    ?2 {
    ?3 ???? public ?DOG(String?name,? int ?age)
    ?4 ???? {
    ?5 ???????? this .name? = ?name;
    ?6 ???????? this .age? = ?age;
    ?7 ????}

    ?8
    ?9 ???? public ?String?getName()
    10 ???? {
    11 ???????? return ? this .name;
    12 ????}

    13
    14 ???? public ? int ?getAge()
    15 ???? {
    16 ???????? return ? this .age;
    17 ????}

    18
    19 ???? public ?Object?clone()
    20 ???? {
    21 ???????? try
    22 ???????? {
    23 ???????????? return ? super .clone();
    24
    25 ????????}
    ? catch ?(CloneNotSupportedException?e)
    26 ???????? {
    27 ???????????? return ? null ;
    28 ????????}

    29 ????}

    30
    31 ???? public ?String?name;
    32
    33 ???? private ? int ?age;
    34
    35 ???? // test
    36 ???? public ? static ? void ?main(String[]?args)
    37 ???? {
    38 ????????DOG?dog1? = ? new ?DOG( " xiaogou " ,? 2 );
    39 ????????DOG?dog2? = ?(DOG)?dog1.clone();
    40 ????????dog1.name? = ? " dagou " ;
    41 ????????System.out.println(dog2.getName());
    42 ????????System.out.println(dog2.getAge());
    43 ????????System.out.println(dog1.getName());
    44 ????????System.out.println(dog1.getAge());
    45
    46 ????}

    47
    48 }

    49



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

    xiaogou
    2
    dagou
    2

    2)深度拷貝

    相對(duì)淺拷貝。實(shí)現(xiàn)對(duì)象中基本數(shù)據(jù)類型和引用數(shù)據(jù)類型的拷貝。

    請(qǐng)先看下面代碼:

    ?

    ?1 class ?AAA
    ?2 {
    ?3 ???? public ?AAA(String?name)
    ?4 ???? {
    ?5 ???????? this .name? = ?name;
    ?6 ????}

    ?7
    ?8 ???? public ?String?name;
    ?9 }

    10
    11 class ?DOG? implements ?Cloneable
    12 {
    13 ???? public ?DOG(String?name,? int ?age,?AAA?birthday)
    14 ???? {
    15 ???????? this .name? = ?name;
    16 ???????? this .age? = ?age;
    17 ???????? this .birthday? = ?birthday;
    18 ????}

    19
    20 ???? public ?String?getName()
    21 ???? {
    22 ???????? return ?name;
    23 ????}

    24
    25 ???? public ? int ?getAge()
    26 ???? {
    27 ???????? return ?age;
    28 ????}

    29
    30 ???? public ?AAA?getBirthday()
    31 ???? {
    32 ???????? return ?birthday;
    33 ????}

    34
    35 ???? public ?String?getBirth(AAA?a)
    36 ???? {
    37 ???????? return ?a.name;
    38 ????}

    39
    40 ???? public ?String?name;
    41
    42 ???? private ? int ?age;
    43
    44 ???? public ?AAA?birthday;
    45
    46 ???? public ?Object?clone()
    47 ???? {
    48 ???????? try
    49 ???????? {
    50 ???????????? super .clone();
    51 ???????????? return ? super .clone();
    52 ????????}
    ? catch ?(Exception?e)
    53 ???????? {
    54 ???????????? return ? null ;
    55 ????????}

    56 ????}

    57 }

    58
    59 public ? class ?TestClone
    60 {
    61 ???? public ? static ? void ?main(String[]?args)
    62 ???? {
    63 ????????AAA?Day? = ? new ?AAA( " test " );
    64 ????????DOG?dog1? = ? new ?DOG( " xiaogou " ,? 2 ,?Day);
    65 ????????DOG?dog2? = ?(DOG)?dog1.clone();
    66 ???????? // ??dog2.birthday?=?(AAA)?dog1.birthday.clone();?
    67 ????????dog1.birthday.name? = ? " 333 " ;
    68 ????????System.out.println(dog1.getBirth(dog1.birthday));
    69 ????????System.out.println(dog2.getBirth(dog2.birthday));
    70 ????}

    71 }

    72


    運(yùn)行結(jié)果是:
    333
    333
    而真正要實(shí)現(xiàn)拷貝還的加點(diǎn)代碼,如下請(qǐng)對(duì)比上面和下面代碼的異同之處:

    ?1 class ?AAA? implements ?Cloneable
    ?2 {
    ?3 ???? public ?AAA(String?name)
    ?4 ???? {
    ?5 ???????? this .name? = ?name;
    ?6 ????}

    ?7
    ?8 ???? public ?Object?clone()
    ?9 ???? {
    10 ???????? try
    11 ???????? {
    12 ???????????? super .clone();
    13 ???????????? return ? super .clone();
    14 ????????}
    ? catch ?(Exception?e)
    15 ???????? {
    16 ???????????? return ? null ;
    17 ????????}

    18 ????}

    19
    20 ???? public ?String?name;
    21 }

    22
    23 class ?DOG? implements ?Cloneable
    24 {
    25 ???? public ?DOG(String?name,? int ?age,?AAA?birthday)
    26 ???? {
    27 ???????? this .name? = ?name;
    28 ???????? this .age? = ?age;
    29 ???????? this .birthday? = ?birthday;
    30 ????}

    31
    32 ???? public ?String?getName()
    33 ???? {
    34 ???????? return ?name;
    35 ????}

    36
    37 ???? public ? int ?getAge()
    38 ???? {
    39 ???????? return ?age;
    40 ????}

    41
    42 ???? public ?AAA?getBirthday()
    43 ???? {
    44 ???????? return ?birthday;
    45 ????}

    46
    47 ???? public ?String?getBirth(AAA?a)
    48 ???? {
    49 ???????? return ?a.name;
    50 ????}

    51
    52 ???? public ?String?name;
    53
    54 ???? private ? int ?age;
    55
    56 ???? public ?AAA?birthday;
    57
    58 ???? public ?Object?clone()
    59 ???? {
    60 ???????? try
    61 ???????? {
    62 ???????????? super .clone();
    63 ???????????? return ? super .clone();
    64 ????????}
    ? catch ?(Exception?e)
    65 ???????? {
    66 ???????????? return ? null ;
    67 ????????}

    68 ????}

    69 }

    70
    71 public ? class ?TestClone
    72 {
    73 ???? public ? static ? void ?main(String[]?args)
    74 ???? {
    75 ????????AAA?Day? = ? new ?AAA( " test " );
    76 ????????DOG?dog1? = ? new ?DOG( " xiaogou " ,? 2 ,?Day);
    77 ????????DOG?dog2? = ?(DOG)?dog1.clone();
    78 ????????dog2.birthday? = ?(AAA)?dog1.birthday.clone(); // 特別注意這里
    79 ????????dog1.birthday.name? = ? " 333 " ;
    80 ????????System.out.println(dog1.getBirth(dog1.birthday));
    81 ????????System.out.println(dog2.getBirth(dog2.birthday));
    82 ????}

    83 }

    84


    運(yùn)行結(jié)果:
    333
    test
    這樣基本就達(dá)到了我們當(dāng)初的母的。


    但是明顯的這種方法還是有許多不足,人們總是希望一個(gè)clone就是對(duì)象直接克隆。而上面還要對(duì)對(duì)象中的對(duì)象遞歸使用clone。下面提供一種更高級(jí)點(diǎn)的做法:

    ?

    ?1 import ?java.io. * ;
    ?2
    ?3 class ?AAA? implements ?Serializable
    ?4 {
    ?5 ???? public ?AAA(String?name)
    ?6 ???? {
    ?7 ???????? this .name? = ?name;
    ?8 ????}

    ?9
    10 ???? public ?String?name;
    11 }

    12
    13 class ?DOG? extends ?SerialCloneable
    14 {
    15 ???? public ?DOG(String?name,? int ?age,?AAA?birthday)
    16 ???? {
    17 ???????? this .name? = ?name;
    18 ???????? this .age? = ?age;
    19 ???????? this .birthday? = ?birthday;
    20 ????}

    21
    22 ???? public ?String?getName()
    23 ???? {
    24 ???????? return ?name;
    25 ????}

    26
    27 ???? public ? int ?getAge()
    28 ???? {
    29 ???????? return ?age;
    30 ????}

    31
    32 ???? public ?AAA?getBirthday()
    33 ???? {
    34 ???????? return ?birthday;
    35 ????}

    36
    37 ???? public ?String?getBirth(AAA?a)
    38 ???? {
    39 ???????? return ?a.name;
    40 ????}

    41
    42 ???? public ?String?name;
    43
    44 ???? private ? int ?age;
    45
    46 ???? public ?AAA?birthday;
    47
    48 ???? public ?Object?clone()
    49 ???? {
    50 ???????? try
    51 ???????? {
    52 ???????????? super .clone();
    53 ???????????? return ? super .clone();
    54 ????????}
    ? catch ?(Exception?e)
    55 ???????? {
    56 ???????????? return ? null ;
    57 ????????}

    58 ????}

    59 }

    60
    61 public ? class ?TestClone
    62 {
    63 ???? public ? static ? void ?main(String[]?args)
    64 ???? {
    65 ????????AAA?Day? = ? new ?AAA( " test " );
    66 ????????DOG?dog1? = ? new ?DOG( " xiaogou " ,? 2 ,?Day);
    67 ????????DOG?dog2? = ?(DOG)?dog1.clone();
    68 ???????? // dog2.birthday?=?(AAA)?dog1.birthday.clone();
    69 ????????dog1.birthday.name? = ? " 333 " ;
    70 ????????System.out.println(dog1.getBirth(dog1.birthday));
    71 ????????System.out.println(dog2.getBirth(dog2.birthday));
    72 ????}

    73 }

    74
    75 class ?SerialCloneable? implements ?Cloneable,?Serializable
    76 {
    77 ???? public ?Object?clone()
    78 ???? {
    79 ???????? try
    80 ???????? {
    81 ????????????ByteArrayOutputStream?bout? = ? new ?ByteArrayOutputStream();
    82 ????????????ObjectOutputStream?out? = ? new ?ObjectOutputStream(bout);
    83 ????????????out.writeObject( this );
    84 ????????????out.close();
    85 ????????????ByteArrayInputStream?bin? = ? new ?ByteArrayInputStream(bout
    86 ????????????????????.toByteArray());
    87 ????????????ObjectInputStream?in? = ? new ?ObjectInputStream(bin);
    88 ????????????Object?ret? = ?in.readObject();
    89 ????????????in.close();
    90 ???????????? return ?ret;
    91 ????????}
    ? catch ?(Exception?e)
    92 ???????? {
    93 ???????????? return ? null ;
    94 ????????}

    95 ????}

    96 }

    97


    輸出:
    333
    test

    上面的代碼用序列化與反序列化實(shí)現(xiàn)了對(duì)象拷貝。比較通用。但是得注意的是其中的類得implements Serializable。

    ?

    3)后記

    我們?nèi)绻脧?qiáng)大的反射機(jī)制+序列化與反序列化,能做出更加靈活的對(duì)象拷貝。有興趣的朋友可以自行去研究。
    我在javaeye上看到一篇短文:http://www.javaeye.com/post/367014 主要講的就是反射在對(duì)象拷貝中的應(yīng)用。


    ?

    posted on 2008-04-28 11:52 -274°C 閱讀(10465) 評(píng)論(6)  編輯  收藏 所屬分類: JAVA


    FeedBack:
    # re: JAVA 對(duì)象拷貝
    2008-04-28 12:51 | Jacky-Q
    這代碼縮進(jìn)真難受....  回復(fù)  更多評(píng)論
      
    # re: JAVA 對(duì)象拷貝
    2008-04-28 14:40 | 々上善若水々
    風(fēng)中葉的吧。  回復(fù)  更多評(píng)論
      
    # re: JAVA 對(duì)象拷貝
    2008-04-29 10:47 | cc
    super .clone();
    return super .clone();
    這里為什么要寫兩次呢,直接寫
    return super .clone();
    不是更好嗎?  回復(fù)  更多評(píng)論
      
    # re: JAVA 對(duì)象拷貝
    2008-04-29 12:44 | java-he
    @ CC
    同意。  回復(fù)  更多評(píng)論
      
    # re: JAVA 對(duì)象拷貝[未登錄]
    2008-04-30 13:56 | java
    不錯(cuò)~  回復(fù)  更多評(píng)論
      
    # re: JAVA 對(duì)象拷貝
    2012-07-02 11:25 | j2
    樓主連什么是遞歸都沒有搞清楚,錯(cuò)別字,錯(cuò)概念太多了  回復(fù)  更多評(píng)論
      

    常用鏈接

    留言簿(21)

    隨筆分類(265)

    隨筆檔案(242)

    相冊(cè)

    JAVA網(wǎng)站

    關(guān)注的Blog

    搜索

    •  

    積分與排名

    • 積分 - 914811
    • 排名 - 40

    最新評(píng)論

    主站蜘蛛池模板: 2022国内精品免费福利视频 | 国产成A人亚洲精V品无码| 亚洲AV无码成人精品区大在线| 亚洲导航深夜福利| 一级毛片不卡片免费观看| 亚洲色成人四虎在线观看 | 在线观看午夜亚洲一区| 黑人粗长大战亚洲女2021国产精品成人免费视频 | 亚洲AV日韩综合一区尤物| 黄页网站免费观看| 国产v亚洲v天堂a无| 中文字幕无码免费久久99| 亚洲卡一卡二卡乱码新区| 毛片免费观看网站| 亚洲男人的天堂网站| 日本一道本高清免费| 免费一级特黄特色大片| 国产午夜亚洲精品午夜鲁丝片| 十八禁视频在线观看免费无码无遮挡骂过 | 黄页网址大全免费观看12网站| www.亚洲精品.com| 一个人免费观看www视频| 国产亚洲精品国看不卡| 99精品免费视频| 久久亚洲精品成人综合| 最近中文字幕大全中文字幕免费| 亚洲人成综合在线播放| 毛片免费在线视频| 国产AV无码专区亚洲AV蜜芽| 五月天婷亚洲天综合网精品偷| 久久久WWW免费人成精品| 久久精品亚洲日本佐佐木明希| **aaaaa毛片免费| 亚洲综合色丁香婷婷六月图片| 国产成人免费全部网站| 一本大道一卡二大卡三卡免费| 亚洲AV中文无码乱人伦下载 | 免费观看a级毛片| 特级毛片爽www免费版| 亚洲乱码国产一区三区| 99久久久国产精品免费牛牛 |