【java开发系列】—— 深克隆和浅克隆

  Java支持咱们对一个对象进行克隆,一般用在装饰模式和原型模式中。那么什么是深克隆,什么是浅克隆呢。java

  【浅克隆】,一般只是对克隆的实例进行复制,但里面的其余子对象,都是共用的。this

  【深克隆】,克隆的时候会复制它的子对象的引用,里面全部的变量和子对象都是又额外拷贝了一份。spa

  下面的两个例子能够很好的说明他们的区别:code

  首先看一下类图

  Husband类有一个对wife的引用,当进行浅克隆的时,wife变量都会指向同一个Wife;而进行深克隆时,会指向不一样的Wife。下面进行一下验证:对象

  【浅克隆】

 1 public Object clone() {  2         Husband husband = null;  3         try{  4             husband = (Husband)super.clone();  5         }catch(CloneNotSupportedException e){  6  e.printStackTrace();  7         }finally{  8             return husband;  9  } 10     }

  【深克隆】

 1 public Object deepClone() throws IOException,ClassNotFoundException {  2         //将对象写到流里
 3         ByteArrayOutputStream bos = new ByteArrayOutputStream();  4         ObjectOutputStream oos = new ObjectOutputStream(bos);  5         oos.writeObject(this);  6         //从流里读回来
 7         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  8         ObjectInputStream ois = new ObjectInputStream(bis);  9         return ois.readObject(); 10     }

  【所有代码】

 1 package com.xingoo.clone;  2 
 3 import java.io.ByteArrayInputStream;  4 import java.io.ByteArrayOutputStream;  5 import java.io.IOException;  6 import java.io.ObjectInputStream;  7 import java.io.ObjectOutputStream;  8 import java.io.Serializable;  9 import java.util.Date;  10 
 11 class Wife implements Serializable{  12     private String name;  13     private Date birthday;  14     
 15     public Wife(){  16         name = "芙蓉姐姐";  17         birthday = new Date();  18  }  19     public Date getBirthday(){  20         return birthday;  21  }  22     
 23     public String getName() {  24         return name;  25  }  26     public void setName(String name) {  27         this.name = name;  28  }  29 }  30 class Husband implements Cloneable,Serializable{  31     private Wife wife;  32     private Date birthday;  33     
 34     public Husband(){  35         wife = new Wife();  36         birthday = new Date();  37  }  38     
 39     public Wife getWife(){  40         return wife;  41  }  42     
 43     public Date getBirthday(){  44         return birthday;  45  }  46     /**  47  * 浅克隆一个对象  48      */
 49     public Object clone() {  50         Husband husband = null;  51         try{  52             husband = (Husband)super.clone();  53         }catch(CloneNotSupportedException e){  54  e.printStackTrace();  55         }finally{  56             return husband;  57  }  58  }  59     /**  60  * 利用串行化深克隆一个对象,把对象以及它的引用读到流里,在写入其余的对象  61  * @return  62  * @throws IOException  63  * @throws ClassNotFoundException  64      */
 65     public Object deepClone() throws IOException,ClassNotFoundException {  66         //将对象写到流里
 67         ByteArrayOutputStream bos = new ByteArrayOutputStream();  68         ObjectOutputStream oos = new ObjectOutputStream(bos);  69         oos.writeObject(this);  70         //从流里读回来
 71         ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());  72         ObjectInputStream ois = new ObjectInputStream(bis);  73         return ois.readObject();  74  }  75 }  76 public class Test {  77     public static void main(String[] args){  78         try{  79             Husband husband = new Husband();  80             System.out.println("husband birthday "+husband.getBirthday().getTime());  81             System.out.println("wife birthday "+husband.getWife().getBirthday().getTime());  82             System.out.println();  83             Husband husband1 = (Husband)husband.clone();  84             System.out.println("husband1 birthday "+husband1.getBirthday().getTime());  85             System.out.println("wife birthday "+husband1.getWife().getBirthday().getTime());  86             System.out.println();  87             System.out.println("是不是同一个husband "+(husband == husband1));  88             System.out.println("是不是同一个wife "+ (husband.getWife() == husband1.getWife()));  89             System.out.println();  90             Husband husband2 = (Husband)husband.deepClone();  91             System.out.println("husband2 birthday "+husband2.getBirthday().getTime());  92             System.out.println("wife birthday "+husband2.getWife().getBirthday().getTime());  93             System.out.println();  94             System.out.println("是不是同一个husband "+(husband == husband2));  95             System.out.println("是不是同一个wife "+ (husband.getWife() == husband2.getWife()));  96         }catch(Exception e){  97  e.printStackTrace();  98  }  99  } 100 }

  【运行结果】

husband birthday 1414247244668 wife birthday 1414247244668 husband1 birthday 1414247244668 wife birthday 1414247244668 是不是同一个husband false 是不是同一个wife true husband2 birthday 1414247244668 wife birthday 1414247244668 是不是同一个husband false 是不是同一个wife false