The NoteBook of EricKong

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

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

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

          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()識別出你要復(fù)制的是哪一個(gè)對象。
                  }

                  
          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的值。
              }

          }

           

           說明:
          ①為什么我們在派生類中覆蓋Object的clone()方法時(shí),一定要調(diào)用super.clone()呢?在運(yùn)行時(shí) 刻,Object中的clone()識別出你要復(fù)制的是哪一個(gè)對象,然后為此對象分配空間,并進(jìn)行對象的復(fù)制,將原始對象的內(nèi)容一一復(fù)制到新對象的存儲空 間中。
          ②繼承自java.lang.Object類的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;
          //常量對象。
              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的教授不會影響s1的教授?代碼改進(jìn)如下。
           
          改進(jìn)使學(xué)生1的Professor不改變(深層次的克?。?/p>

          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.利用串行化來做深復(fù)制
              把對象寫到流里的過程是串行化(Serilization)過程,但是在Java程序師圈子里又非常形象地稱為“冷凍”或者“腌咸菜(picking)” 過程;而把對象從流中讀出來的并行化(Deserialization)過程則叫做“解凍”或者“回鮮(depicking)”過程。應(yīng)當(dāng)指出的是,寫在 流里的是對象的一個(gè)拷貝,而原對象仍然存在于JVM里面,因此“腌成咸菜”的只是對象的一個(gè)拷貝,Java咸菜還可以回鮮。
          在Java語言里深復(fù)制一個(gè)對象,常??梢韵仁箤ο髮?shí)現(xiàn)Serializable接口,然后把對象(實(shí)際上只是對象的一個(gè)拷貝)寫到一個(gè)流里(腌成咸菜),再從流里讀出來(把咸菜回鮮),便可以重建對象。
          如下為深復(fù)制源代碼。

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

                 這樣做的前提是對象以及對象內(nèi)部所有引用到的對象都是可串行化的,否則,就需要仔細(xì)考察那些不可串行化的對象可否設(shè)成transient,從而將之排除在復(fù)制過程之外。上例代碼改進(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;
          //常量對象。
              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
              
          {
                   
          //將對象寫到流里
                    ByteArrayOutoutStream bo=new ByteArrayOutputStream();
                    ObjectOutputStream oo
          =new ObjectOutputStream(bo);
                    oo.writeObject(
          this);
                    
          //從流里讀出來
                    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) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 惠来县| 宁阳县| 固阳县| 灵宝市| 申扎县| 迁西县| 宁波市| 商丘市| 安平县| 安乡县| 西城区| 敖汉旗| 玉山县| 增城市| 岳阳县| 潼关县| 裕民县| 泸溪县| 东乡| 旅游| 罗江县| 汝阳县| 黑水县| 安远县| 嘉定区| 九龙城区| 比如县| 高安市| 咸阳市| 普宁市| 北票市| 从江县| 石景山区| 鹰潭市| 南雄市| 平遥县| 松江区| 郯城县| 江北区| 东方市| 理塘县|