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(100.00);
dhClone.setValue(200.00);
System.out.println("Original:" + dh.getValue());
System.out.println("Clone :" + dhClone.getValue());
}
}
上面的程式碼生成以下結果。
Original:100.0
Clone :100.0
Original:100.0
Clone :200.0
以下程式碼不從clone()
方法返回物件型別,該方法僅在Java5或更高版本中編譯。
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());
}
}
上面的程式碼生成以下結果。
Original:100.0
Clone :100.0
Original:200.0
Clone :200.0
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());
}
}
執行上面的程式碼,將生成以下結果 -
Original:100.0
Clone :100.0
Original:200.0
Clone :100.0