浅复制shallow copy,指在复制源对象中,如果某个成员数据是一个对象(除了String和所有包装类对象之外),clone()方法只是复制对这个成员对象的引用。即在复制后的对象中,它所具有的成员对象,只是对原来成员对象的引用,并没有真正复制这个成员数据。但对所有基本类型成员数据,包括字符串以及包装类成员对象,clone()则执行真正复制。即分配内存地址,并将它们拷贝到这个内存中。
浅复制的对象对其成员对象的任何修改,实际上是对源对象中成员对象的修改;反之亦然。但对这两个对象中其他类型成员数据的修改,则不会相互影响,因为这些成员数据有其自己独立的拷贝。
示例如下:
public class OtherClass {
String name;
public OtherClass(String name) {
this.name = name;
}
@Override
public String toString() {
return "OtherClass [name=" + name + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class SomeClass implements Cloneable{
OtherClass other;
Integer number;
int n;
public SomeClass(String title, Integer number, int n) {
other = new OtherClass(title);
this.number = number;
this.n = n;
}
public String getTitle() {
return other.getName();
}
public void setTitle(String title) {
this.other.name = title;
}
public Integer getNumber() {
return number;
}
public void setNumber(Integer number) {
this.number = number;
}
public int getN() {
return n;
}
public void setN(int n) {
this.n = n;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "SomeClass [title=" + other.name + ", number=" + number + ", n=" + n
+ "]";
}
}
public class CloneableTest {
public static void main(String[] args) throws CloneNotSupportedException {
SomeClass sourceObj = new SomeClass("Java", 100, 10);
SomeClass targetObj = (SomeClass) sourceObj.clone();
System.out.println("Content of sorceObj:" + sourceObj);
System.out.println("Content of targetObj:" + targetObj);
targetObj.setTitle("JSP");
sourceObj.setNumber(200);
sourceObj.setN(0);
System.out.println("After modify...");
System.out.println("Content of sorceObj:" + sourceObj);
System.out.println("Content of targetObj:" + targetObj);
}
}
输出结果为:
Content of sorceObj:SomeClass [title=Java, number=100, n=10]
Content of targetObj:SomeClass [title=Java, number=100, n=10]
After modify...
Content of sorceObj:SomeClass [title=JSP, number=200, n=0]
Content of targetObj:SomeClass [title=JSP, number=100, n=10]
可以看到,clone()方法对sourceObj对象中的成员对象other仅复制引用。所以targetObj对other的修改,即是对sourceObj的修改,反之亦然。当代码中利用sourceObj修改包装类成员number和基本数据类型n时,并不影响targetObj所对应的这些数据成员的值。
覆盖clone()方法,提供对成员对象真正复制的代码,则可以实现深复制。
修改clone()方法如下:
protected Object clone() throws CloneNotSupportedException {
SomeClass someClass = new SomeClass(this);
return someClass;
}
修改SomeClass对象,增加一个拷贝构造函数:
public SomeClass(SomeClass someClass) {
this.other = new OtherClass(someClass.getTitle());
this.number = someClass.getNumber();
this.n = someClass.getN();
}
执行CloneTest,结果如下:
Content of sorceObj:SomeClass [title=Java, number=100, n=10]
Content of targetObj:SomeClass [title=Java, number=100, n=10]
After modify...
Content of sorceObj:SomeClass [title=Java, number=200, n=0]
Content of targetObj:SomeClass [title=JSP, number=100, n=10]