The NoteBook of EricKong

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            611 Posts :: 1 Stories :: 190 Comments :: 0 Trackbacks

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

          2.Java的clone()方法
          ⑴clone方法將對象復制了一份并返回給調用者。一般而言,clone()方法滿足:
          ①對任何的對象x,都有x.clone() !=x//克隆對象與原對象不是同一個對象
          ②對任何的對象x,都有x.clone().getClass()= =x.getClass()//克隆對象與原對象的類型一樣
          ③如果對象x的equals()方法定義恰當,那么x.clone().equals(x)應該成立。
           
          ⑵Java中對象的克隆
          ①為了獲取對象的一份拷貝,我們可以利用Object類的clone()方法。
          ②在派生類中覆蓋基類的clone()方法,并聲明為public。
          ③在派生類的clone()方法中,調用super.clone()。
          ④在派生類中實現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()識別出你要復制的是哪一個對象。
                  }

                  
          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);//修改學生2后,不影響學生1的值。
              }

          }

           

           說明:
          ①為什么我們在派生類中覆蓋Object的clone()方法時,一定要調用super.clone()呢?在運行時 刻,Object中的clone()識別出你要復制的是哪一個對象,然后為此對象分配空間,并進行對象的復制,將原始對象的內容一一復制到新對象的存儲空 間中。
          ②繼承自java.lang.Object類的clone()方法是淺復制。以下代碼可以證明之。

          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;
          //學生1和學生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);//學生1的教授成為lisi,age為30。
              }

          }

          那應該如何實現深層次的克隆,即修改s2的教授不會影響s1的教授?代碼改進如下。
           
          改進使學生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);//學生1的教授不改變。
              }


          }

           
          3.利用串行化來做深復制
              把對象寫到流里的過程是串行化(Serilization)過程,但是在Java程序師圈子里又非常形象地稱為“冷凍”或者“腌咸菜(picking)” 過程;而把對象從流中讀出來的并行化(Deserialization)過程則叫做“解凍”或者“回鮮(depicking)”過程。應當指出的是,寫在 流里的是對象的一個拷貝,而原對象仍然存在于JVM里面,因此“腌成咸菜”的只是對象的一個拷貝,Java咸菜還可以回鮮。
          在Java語言里深復制一個對象,常常可以先使對象實現Serializable接口,然后把對象(實際上只是對象的一個拷貝)寫到一個流里(腌成咸菜),再從流里讀出來(把咸菜回鮮),便可以重建對象。
          如下為深復制源代碼。

          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());
          }

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

          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;
          //學生1和學生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); //學生1的教授不改變。
               }

          }

          posted on 2010-07-22 09:49 Eric_jiang 閱讀(298) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 灯塔市| 和林格尔县| 安徽省| 江口县| 沅江市| 进贤县| 龙井市| 习水县| 河北区| 阿克陶县| 固原市| 涿鹿县| 仁化县| 白玉县| 卓资县| 扎赉特旗| 长岛县| 宜黄县| 登封市| 嵊州市| 周宁县| 宁蒗| 油尖旺区| 永仁县| 桂平市| 金川县| 延吉市| SHOW| 普定县| 宿迁市| 凯里市| 杭州市| 和平县| 鄂伦春自治旗| 娱乐| 颍上县| 雷山县| 房产| 望都县| 建瓯市| 叙永县|