这里我们就可以引入两个专业的术语:浅克隆(shallow clone)和深克隆(deep clone)。
所谓的浅克隆,顾名思义就是很表面的很表层的克隆,如果我们要克隆Administrator对象,只克隆他自身以及他包含的所有对象的引用地址
而深克隆,就是非浅克隆。克隆除自身以外所有的对象,包括自身所包含的所有对象实例。至于深克隆的层次,由具体的需求决定,也有“N层克隆”一说。
但是,所有的基本(primitive)类型数据,无论是浅克隆还是深克隆,都会进行原值克隆。毕竟他们都不是对象,不是存储在堆中。注意:基本数据类型并不包括他们对应的包装类。
 
四、说明:
克隆必须满足的条件:
a.对任何的对象x,都有:x.clone() != x,即克隆对象与原对象不是同一个对象。
b.对任何的对象x,都有:x.clone().getClass() == x.get getClass(),即克隆对象与原对象的类型是一样的。 c.如果对象x的equals()方法定义恰当的话,那么x.clone().equals(x)应当是成立的。
在java中实现clone()应该满足这三个条件。

浅复制复制了值类型对象,对于引用类型对象,只复制了引用,它指向原来引用的对象。Java中clone为浅复制。
深复制对值类型和引用类型的对象都生成一份新的拷贝. Java中可以通过串行化来进行深复制,前提是对象以及对象内部所引用的对象都是可串行化的,否则需要考虑将那些不可串行化的对象可否设为transient,排除 在复制过程之外。
 
Part VI
接下来要重点介绍一下使用java.lang.Serializable来实现对象的深度克隆。
首先,我们编写一个工具类并提供cloneTo()方法。

import java.io.ByteArrayInputStream;    

import java.io.ByteArrayOutputStream;    

import java.io.IOException;    

import java.io.ObjectInputStream;    

import java.io.ObjectOutputStream;    

public abstract class BeanUtil {    

@SuppressWarnings("unchecked")    

public static T cloneTo(T src) throws RuntimeException {    

ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();    

ObjectOutputStream out = null;    

ObjectInputStream in = null;    

T dist = null;    

try {    

out = new ObjectOutputStream(memoryBuffer);    

out.writeObject(src);    

out.flush();    

in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
    
dist = (T) in.readObject();    

} catch (Exception e) {    

throw new RuntimeException(e);    

} finally {    

if (out != null)    

try {    

out.close();    

out = null;    

} catch (IOException e) {    

throw new RuntimeException(e);    

}    

if (in != null)    

try {    

in.close();    

in = null;    

} catch (IOException e) {    

throw new RuntimeException(e);    

}    

}    

return dist;    

}    

}
    
看不懂,没关系,直接拿去用就可以了。嘻嘻。
    
接下来我们测试一下是否能通过这个工具来实现深度克隆。
    
又是这个可爱的TestCase,可怜的每次都要动他……
    

import java.util.Date;    

import org.junit.Test;    

public class TestCase {    



@Test    

public void testCloneTo() {    

Administrator src = new Administrator(new User("Kent", "123456", new Date()), true);
    
Administrator dist = BeanUtil.cloneTo(src);    



System.out.println(src == dist); // false    

System.out.println(src.equals(dist)); // true    



System.out.println(src.getUser() == dist.getUser()); //false ! Well done!    

System.out.println(src.getUser().equals(dist.getUser())); //true    

}    



}
好了,无论你的对象有多么的复杂,只要这些对象都能够实现java.lang.Serializable接口,就可以进行克隆,而且这种克隆的机制是JVM完成的,不需要修改实体类的代码,方便多了。