Java支持我们对一个对象进行克隆,通常用在装饰模式和原型模式中。那么什么是深克隆,什么是浅克隆呢。
【浅克隆】,通常只是对克隆的实例进行复制,但里面的其他子对象,都是共用的。
【深克隆】,克隆的时候会复制它的子对象的引用,里面所有的变量和子对象都是又额外拷贝了一份。
下面的两个例子可以很好的说明他们的区别:
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