这里我们就可以引入两个专业的术语:浅克隆(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完成的,不需要修改实体类的代码,方便多了。