The NoteBook of EricKong

            BlogJava :: 首頁(yè) :: 聯(lián)系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

          1.淺復(fù)制與深復(fù)制概念
          ⑴淺復(fù)制(淺克隆)
          被復(fù)制對(duì)象的所有變量都含有與原來(lái)的對(duì)象相同的值,而所有的對(duì)其他對(duì)象的引用仍然指向原來(lái)的對(duì)象。換言之淺復(fù)制僅僅復(fù)制所考慮的對(duì)象,而不復(fù)制它所引用的對(duì)象
           
          ⑵深復(fù)制(深克?。?br /> 被復(fù)制對(duì)象的所有變量都含有與原來(lái)的對(duì)象相同的值,除去那些引用其他對(duì)象的變量。那些引用其他對(duì)象的變量將指向被復(fù)制過(guò)的新對(duì)象,而不再是原有的那些被引用的對(duì)象。換言之,深復(fù)制把要復(fù)制的對(duì)象所引用的對(duì)象都復(fù)制了一遍。

          2.Java的clone()方法
          ⑴clone方法將對(duì)象復(fù)制了一份并返回給調(diào)用者。一般而言,clone()方法滿足:
          ①對(duì)任何的對(duì)象x,都有x.clone() !=x//克隆對(duì)象與原對(duì)象不是同一個(gè)對(duì)象
          ②對(duì)任何的對(duì)象x,都有x.clone().getClass()= =x.getClass()//克隆對(duì)象與原對(duì)象的類(lèi)型一樣
          ③如果對(duì)象x的equals()方法定義恰當(dāng),那么x.clone().equals(x)應(yīng)該成立。
           
          ⑵Java中對(duì)象的克隆
          ①為了獲取對(duì)象的一份拷貝,我們可以利用Object類(lèi)的clone()方法。
          ②在派生類(lèi)中覆蓋基類(lèi)的clone()方法,并聲明為public。
          ③在派生類(lèi)的clone()方法中,調(diào)用super.clone()。
          ④在派生類(lèi)中實(shí)現(xiàn)Cloneable接口。
           
          請(qǐng)看如下代碼:

          class Student implements Cloneable
          {
              String name;
              
          int age;
              Student(String name,
          int age)
              
          {
                  
          this.name=name;
                  
          this.age=age;
              }

              
          public Object clone()
              
          {
                  Object o
          =null;
                  
          try
                  
          {
                  o
          =(Student)super.clone();//Object中的clone()識(shí)別出你要復(fù)制的是哪一個(gè)對(duì)象。
                  }

                  
          catch(CloneNotSupportedException e)
                  
          {
                      System.out.println(e.toString());
                  }

                  
          return o;
              }


              
          public static void main(String[] args)
              
          {
                    Student s1
          =new Student("zhangsan",18);
                    Student s2
          =(Student)s1.clone();
                    s2.name
          ="lisi";
                   s2.age
          =20;
                   System.out.println(
          "name="+s1.name+","+"age="+s1.age);//修改學(xué)生2后,不影響學(xué)生1的值。
              }

          }

           

           說(shuō)明:
          ①為什么我們?cè)谂缮?lèi)中覆蓋Object的clone()方法時(shí),一定要調(diào)用super.clone()呢?在運(yùn)行時(shí) 刻,Object中的clone()識(shí)別出你要復(fù)制的是哪一個(gè)對(duì)象,然后為此對(duì)象分配空間,并進(jìn)行對(duì)象的復(fù)制,將原始對(duì)象的內(nèi)容一一復(fù)制到新對(duì)象的存儲(chǔ)空 間中。
          ②繼承自java.lang.Object類(lèi)的clone()方法是淺復(fù)制。以下代碼可以證明之。

          class Professor 
          {
              String name;
              
          int age;
              Professor(String name,
          int age)
              
          {
                  
          this.name=name;
                  
          this.age=age;
              }

          }

          class Student implements Cloneable
          {
              String name;
          //常量對(duì)象。
              int age;
              Professor p;
          //學(xué)生1和學(xué)生2的引用值都是一樣的。
              Student(String name,int age,Professor p)
              
          {
                  
          this.name=name;
                  
          this.age=age;
                  
          this.p=p;
              }

              
          public Object clone()
              
          {
                  Student o
          =null;
                  
          try
                  
          {
                      o
          =(Student)super.clone();
                  }

                  
          catch(CloneNotSupportedException e)
                  
          {
                      System.out.println(e.toString());
                  }

                  o.p
          =(Professor)p.clone();
                  
          return o;
              }

              
          public static void main(String[] args)
              
          {
                    Professor p
          =new Professor("wangwu",50);
                    Student s1
          =new Student("zhangsan",18,p);
                    Student s2
          =(Student)s1.clone();
                    s2.p.name
          ="lisi";
                   s2.p.age
          =30;
              System.out.println(
          "name="+s1.p.name+","+"age="+s1.p.age);//學(xué)生1的教授成為lisi,age為30。
              }

          }

          那應(yīng)該如何實(shí)現(xiàn)深層次的克隆,即修改s2的教授不會(huì)影響s1的教授?代碼改進(jìn)如下。
           
          改進(jìn)使學(xué)生1的Professor不改變(深層次的克隆)

          class Professor implements Cloneable
          {
              String name;
              
          int age;
              Professor(String name,
          int age)
              
          {
                  
          this.name=name;
                  
          this.age=age;
              }

              
          public Object clone()
              
          {
                  Object o
          =null;
                  
          try
                  
          {
                      o
          =super.clone();
                  }

                  
          catch(CloneNotSupportedException e)
                  
          {
                      System.out.println(e.toString());
                  }

                  
          return o;
              }

          }

          class Student implements Cloneable
          {
              String name;
              
          int age;
              Professor p;
              Student(String name,
          int age,Professor p)
              
          {
                  
          this.name=name;
                  
          this.age=age;
                  
          this.p=p;
              }

              
          public Object clone()
              
          {
                  Student o
          =null;
                  
          try
                  
          {
                      o
          =(Student)super.clone();
                  }

                  
          catch(CloneNotSupportedException e)
                  
          {
                      System.out.println(e.toString());
                  }

                  o.p
          =(Professor)p.clone();
                  
          return o;
              }

              
          public static void main(String[] args)
              
          {
                    Professor p
          =new Professor("wangwu",50);
                    Student s1
          =new Student("zhangsan",18,p);
                    Student s2
          =(Student)s1.clone();
                    s2.p.name
          ="lisi";
                   s2.p.age
          =30;
                   System.out.println(
          "name="+s1.p.name+","+"age="+s1.p.age);//學(xué)生1的教授不改變。
              }


          }

           
          3.利用串行化來(lái)做深復(fù)制
              把對(duì)象寫(xiě)到流里的過(guò)程是串行化(Serilization)過(guò)程,但是在Java程序師圈子里又非常形象地稱為“冷凍”或者“腌咸菜(picking)” 過(guò)程;而把對(duì)象從流中讀出來(lái)的并行化(Deserialization)過(guò)程則叫做“解凍”或者“回鮮(depicking)”過(guò)程。應(yīng)當(dāng)指出的是,寫(xiě)在 流里的是對(duì)象的一個(gè)拷貝,而原對(duì)象仍然存在于JVM里面,因此“腌成咸菜”的只是對(duì)象的一個(gè)拷貝,Java咸菜還可以回鮮。
          在Java語(yǔ)言里深復(fù)制一個(gè)對(duì)象,常常可以先使對(duì)象實(shí)現(xiàn)Serializable接口,然后把對(duì)象(實(shí)際上只是對(duì)象的一個(gè)拷貝)寫(xiě)到一個(gè)流里(腌成咸菜),再?gòu)牧骼镒x出來(lái)(把咸菜回鮮),便可以重建對(duì)象。
          如下為深復(fù)制源代碼。

          public Object deepClone()
          {
                
          //將對(duì)象寫(xiě)到流里
                ByteArrayOutoutStream bo=new ByteArrayOutputStream();
                ObjectOutputStream oo
          =new ObjectOutputStream(bo);
                oo.writeObject(
          this);
                
          //從流里讀出來(lái)
                ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
                ObjectInputStream oi
          =new ObjectInputStream(bi);
                
          return(oi.readObject());
          }

                 這樣做的前提是對(duì)象以及對(duì)象內(nèi)部所有引用到的對(duì)象都是可串行化的,否則,就需要仔細(xì)考察那些不可串行化的對(duì)象可否設(shè)成transient,從而將之排除在復(fù)制過(guò)程之外。上例代碼改進(jìn)如下。
           

          class Professor implements Serializable
          {
              String name;
              
          int age;
              Professor(String name,
          int age)
              
          {
                  
          this.name=name;
                  
          this.age=age;
              }

          }

          class Student implements Serializable
          {
              String name;
          //常量對(duì)象。
              int age;
              Professor p;
          //學(xué)生1和學(xué)生2的引用值都是一樣的。
              Student(String name,int age,Professor p)
              
          {
                  
          this.name=name;
                  
          this.age=age;
                  
          this.p=p;
              }

              
          public Object deepClone() throws IOException,OptionalDataException,ClassNotFoundException
              
          {
                   
          //將對(duì)象寫(xiě)到流里
                    ByteArrayOutoutStream bo=new ByteArrayOutputStream();
                    ObjectOutputStream oo
          =new ObjectOutputStream(bo);
                    oo.writeObject(
          this);
                    
          //從流里讀出來(lái)
                    ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray());
                    ObjectInputStream oi
          =new ObjectInputStream(bi);
                    
          return(oi.readObject());
               }

              
          public static void main(String[] args)
              
          {
                     Professor p
          =new Professor("wangwu",50);
                     Student s1
          =new Student("zhangsan",18,p);
                     Student s2
          =(Student)s1.deepClone();
                     s2.p.name
          ="lisi";
                    s2.p.age
          =30;
                    System.out.println(
          "name="+s1.p.name+","+"age="+s1.p.age); //學(xué)生1的教授不改變。
               }

          }

          posted on 2010-07-22 09:49 Eric_jiang 閱讀(301) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Java
          主站蜘蛛池模板: 安塞县| 伽师县| 舟曲县| 兴城市| 德江县| 正镶白旗| 汤阴县| 桃园市| 恩平市| 蕲春县| 城口县| 政和县| 桂平市| 佛坪县| 上林县| 镇康县| 东乡族自治县| 逊克县| 元江| 昂仁县| 滦平县| 南平市| 张北县| 普格县| 富顺县| 宜昌市| 绥中县| 资中县| 泗洪县| 嘉峪关市| 黄山市| 嘉禾县| 阿瓦提县| 钦州市| 临泽县| 远安县| 甘德县| 彭水| 佳木斯市| 公安县| 建湖县|