Java中的深拷貝(深複製)和淺拷貝(淺複製)

深拷貝(深複製)和淺拷貝(淺複製)是兩個比較通用的概念,尤爲在C++語言中,若不弄懂,則會在delete的時候出問題,可是咱們在這幸虧用的是Java。雖然java自動管理對象的回收,但對於深拷貝(深複製)和淺拷貝(淺複製),咱們仍是要給予足夠的重視,由於有時這兩個概念每每會給咱們帶來不小的困惑。java

淺拷貝是指拷貝對象時僅僅拷貝對象自己(包括對象中的基本變量),而不拷貝對象包含的引用指向的對象。深拷貝不只拷貝對象自己,並且拷貝對象包含的引用指向的全部對象。舉例來講更加清楚:對象A1中包含對B1的引用,B1中包含對C1的引用。淺拷貝A1獲得A2,A2 中依然包含對B1的引用,B1中依然包含對C1的引用。深拷貝則是對淺拷貝的遞歸,深拷貝A1獲得A2,A2中包含對B2(B1的copy)的引用,B2 中包含對C2(C1的copy)的引用。框架

若不對clone()方法進行改寫,則調用此方法獲得的對象即爲淺拷貝,下面咱們着重談一下深拷貝。this

運行下面的程序,看一看淺拷貝:spa

 

class  Professor0 implements  Cloneable {
     String name;
     int  age;
 
     Professor0(String name, int  age) {
         this .name = name;
         this .age = age;
     }
 
     public  Object clone() throws  CloneNotSupportedException {
         return  super .clone();
     }
}
 
class  Student0 implements  Cloneable {
     String name; // 常量對象。
     int  age;
     Professor0 p; // 學生1和學生2的引用值都是同樣的。
 
     Student0(String name, int  age, Professor0 p) {
         this .name = name;
         this .age = age;
         this .p = p;
     }
 
     public  Object clone() {
         Student0 o = null ;
         try  {
             o = (Student0) super .clone();
         } catch  (CloneNotSupportedException e) {
             System.out.println(e.toString());
         }
 
         return  o;
     }
}
 
public  class  ShallowCopy {
     public  static  void  main(String[] args) {
         Professor0 p = new  Professor0( "wangwu" , 50 );
         Student0 s1 = new  Student0( "zhangsan" , 18 , p);
         Student0 s2 = (Student0) s1.clone();
         s2.p.name = "lisi" ;
         s2.p.age = 30 ;
         s2.name = "z" ;
         s2.age = 45 ;
         System.out.println( "學生s1的姓名:"  + s1.name + "\n學生s1教授的姓名:"  + s1.p.name + ","  + "\n學生s1教授的年紀"  + s1.p.age); // 學生1的教授
     }
}

 

s2變了,但s1也變了,證實s1的p和s2的p指向的是同一個對象。這在咱們有的實際需求中,卻不是這樣,於是咱們須要深拷貝:code

 

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  class  DeepCopy {
     public  static  void  main(String args[]) {
         long  t1 = System.currentTimeMillis();
         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的教授不改變。
         long  t2 = System.currentTimeMillis();
         System.out.println(t2-t1);
     }
}

 

固然咱們還有一種深拷貝方法,就是將對象串行化:對象

 

import  java.io.*;
//Serialization is time-consuming
class  Professor2 implements  Serializable {
     /**
      *
      */
     private  static  final  long  serialVersionUID = 1L;
     String name;
     int  age;
 
     Professor2(String name, int  age) {
         this .name = name;
         this .age = age;
     }
}
 
class  Student2 implements  Serializable {
     /**
      *
      */
     private  static  final  long  serialVersionUID = 1L;
     String name; // 常量對象。
     int  age;
     Professor2 p; // 學生1和學生2的引用值都是同樣的。
 
     Student2(String name, int  age, Professor2 p) {
         this .name = name;
         this .age = age;
         this .p = p;
     }
 
     public  Object deepClone() throws  IOException, OptionalDataException,
             ClassNotFoundException {
         // 將對象寫到流裏
         ByteArrayOutputStream 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  class  DeepCopy2 {
 
     /**
      * @param args
      */
     public  static  void  main(String[] args) throws  OptionalDataException,
             IOException, ClassNotFoundException {
         long  t1 = System.currentTimeMillis();
         Professor2 p = new  Professor2( "wangwu" , 50 );
         Student2 s1 = new  Student2( "zhangsan" , 18 , p);
         Student2 s2 = (Student2) s1.deepClone();
         s2.p.name = "lisi" ;
         s2.p.age = 30 ;
         System.out.println( "name="  + s1.p.name + ","  + "age="  + s1.p.age); // 學生1的教授不改變。
         long  t2 = System.currentTimeMillis();
         System.out.println(t2-t1);
     }
 
}

 

可是串行化卻很耗時,在一些框架中,咱們即可以感覺到,它們每每將對象進行串行化後進行傳遞,耗時較多。blog

相關文章
相關標籤/搜索