Java面向对象设计 - Java Object.Clone方法
Java不提供克隆(复制)对象的自动机制。
克隆对象意味着逐位复制对象的内容。
要支持克隆操作,请在类中实现clone()方法。
Object类中的clone()方法的声明如下:protected Object clone() throws CloneNotSupportedException
clone()方法声明为protected。因此,我们不能从客户端代码调用它。以下代码无效:Object obj = new Object();
Object clone = obj.clone(); // Error. Cannot access protected clone() method
我们需要在类中声明clone()方法public克隆类的对象。
它的返回类型是Object。这意味着您将需要转换clone()方法的返回值。
假设MyClass是可克隆的。克隆代码将如下所示:MyClass mc = new MyClass();
MyClass clone = (MyClass)mc.clone(); // Need to use a cast
Object类中的clone()方法会抛出CloneNotSupportedException。
要调用clone()方法,我们需要将调用放在try-catch块中,或者重新抛出异常。
例子
以下代码显示了如何实现克隆方法。class MyClass implements Cloneable {
private double value;
public MyClass(double value) {
this.value = value;
}
public void setValue(double value) {
this.value = value;
}
public double getValue() {
return this.value;
}
public Object clone() {
MyClass copy = null;
try {
copy = (MyClass) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return copy;
}
}
public class Main {
public static void main(String[] args) {
MyClass dh = new MyClass(100.00);
MyClass dhClone = (MyClass) dh.clone();
System.out.println("Original:" + dh.getValue());
System.out.println("Clone :" + dhClone.getValue());
dh.setValue(200.00);
dhClone.setValue(400.00);
System.out.println("Original:" + dh.getValue());
System.out.println("Clone :" + dhClone.getValue());
}
}
上面的代码生成以下结果。
例2
以下代码不从clone方法返回对象类型,该方法仅在Java 5或更高版本中编译。class MyClass implements Cloneable {
public MyClass clone() {
Object copy = null;
return (MyClass)copy;
}
}
下面的代码展示了如何做浅层克隆。class MyClass implements Cloneable {
private double value;
public MyClass(double value) {
this.value = value;
}
public void setValue(double value) {
this.value = value;
}
public double getValue() {
return this.value;
}
public Object clone() {
MyClass copy = null;
try {
copy = (MyClass) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return copy;
}
}
class ShallowClone implements Cloneable {
private MyClass holder = new MyClass(0.0);
public ShallowClone(double value) {
this.holder.setValue(value);
}
public void setValue(double value) {
this.holder.setValue(value);
}
public double getValue() {
return this.holder.getValue();
}
public Object clone() {
ShallowClone copy = null;
try {
copy = (ShallowClone) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return copy;
}
}
public class Main {
public static void main(String[] args) {
ShallowClone sc = new ShallowClone(100.00);
ShallowClone scClone = (ShallowClone) sc.clone();
System.out.println("Original:" + sc.getValue());
System.out.println("Clone :" + scClone.getValue());
sc.setValue(200.00);
System.out.println("Original:" + sc.getValue());
System.out.println("Clone :" + scClone.getValue());
}
}
上面的代码生成以下结果。
例3
ShallowClone类的clone()方法中的代码与MyClass类的clone()方法相同。
当ShallowClone类使用super.clone()调用Object类的clone()方法时,它会接收自身的浅拷贝。也就是说,它与其克隆共享其实例变量中使用的DoubleHolder对象。
在深层克隆中,您需要克隆对象的所有引用实例变量引用的所有对象。class MyClass implements Cloneable {
private double value;
public MyClass(double value) {
this.value = value;
}
public void setValue(double value) {
this.value = value;
}
public double getValue() {
return this.value;
}
public Object clone() {
MyClass copy = null;
try {
copy = (MyClass) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return copy;
}
}
class DeepClone implements Cloneable {
private MyClass holder = new MyClass(0.0);
public DeepClone(double value) {
this.holder.setValue(value);
}
public void setValue(double value) {
this.holder.setValue(value);
}
public double getValue() {
return this.holder.getValue();
}
public Object clone() {
DeepClone copy = null;
try {
copy = (DeepClone) super.clone();
copy.holder = (MyClass) this.holder.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return copy;
}
}
public class Main {
public static void main(String[] args) {
DeepClone sc = new DeepClone(100.00);
DeepClone scClone = (DeepClone) sc.clone();
System.out.println("Original:" + sc.getValue());
System.out.println("Clone :" + scClone.getValue());
sc.setValue(200.00);
System.out.println("Original:" + sc.getValue());
System.out.println("Clone :" + scClone.getValue());
}
}
上面的代码生成以下结果。