Java對象克隆
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
實例-2
以下代碼不從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
實例-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());
}
}
執行上面的代碼,將生成以下結果 -
Original:100.0
Clone :100.0
Original:200.0
Clone :100.0