![](/img/trans.png)
[英]Understanding what happens when we override the clone method with and without invoking super.clone?
[英]Why when implementing clone method we return super.clone() not this clone()
public abstract class Shape implements Cloneable {
private String id;
protected String type;
abstract void draw();
public String getType(){
return type;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public Object clone() {
Object clone = null;
try {
clone = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return clone;
}
}
假設我想獲得一個對象的克隆然后我們總是返回super.clone()
如果我想克隆一個對象然后我想這是我想要克隆的對象。我是克隆的初學者。
超類clone
方法應該是Object.clone()
或者它應該將1 (最終)委托給Object.clone()
。 這是一個“神奇”的方法,它知道如何創建當前實例的實際類的新實例。
當然,如果你試圖像這樣實現克隆:
public Object clone() {
return clone();
}
你會創建一個快速以StackOverflowError
結束的遞歸循環。
1 - 如果super.clone()
最終沒有委托給Object.clone()
,那么它將無法克隆Shape
定義的字段的值及其具體的子類型。
請注意,這個特定的例子, clone()
可以簡化為:
public Object clone() {
return super.clone();
}
Shape
類將Object
作為其超類,並且Object.clone()
將拋出CloneNotSupportedException
的唯一情況是實際類沒有implement
Cloneable
接口。 但是Shape
就是這樣做的。
事實上。 clone()
所有聲明實際上都是為了提高Object
API中protected
的clone()
版本的可見性。
無論你使用super
還是this
,被解除引用的對象都是相同的。 但是,由於您使用this.clone()
覆蓋clone
方法會導致(無限)遞歸。 使用super.clone()
確保調用超類的clone
實現。
請注意,無論實際類型如何, Object.clone
復制整個對象。
覆蓋方法時,您唯一需要注意的是:
public
的可見度(如果你想要的話) super.clone()
復制的任何可變對象 以下示例顯示了克隆對象的常用方法
public class Sheep implements Cloneable {
private String name;
public Sheep(String name) {
this.name = name;
}
public static void main(String[] args) throws CloneNotSupportedException {
Sheep s = new Sheep("dolly");
Sheep s2 = (Sheep) s.clone();
s2.numbers[0] = 42;
System.out.println(s);
System.out.println(s2);
}
private int[] numbers = new int[1];
@Override
public Object clone() throws CloneNotSupportedException {
Sheep clone = (Sheep) super.clone();
// copy referenced mutable objects
clone.numbers = this.numbers.clone();
// no need to copy name, since String is immutable
return clone;
}
@Override
public String toString() {
return "Sheep{" + "name=" + name + ", numbers=" + Arrays.toString(numbers) + '}';
}
}
請注意,注釋掉該行
clone.numbers = this.numbers.clone();
將導致陣列相同。
在您的示例中, super.clone()
引用了Object.clone()
其JavaDoc聲明:
否則,此方法創建此對象的類的新實例,並使用該對象的相應字段的內容初始化其所有字段,就像通過賦值一樣; 這些字段的內容本身不會被克隆。 因此,該方法執行該對象的“淺拷貝”,而不是“深拷貝”操作。
這意味着如果淺拷貝就足夠了,那么使用super.clone()
就足夠了。 覆蓋有兩個目的:
clone()
public( Object.clone()
受保護) null
處理子類不能正常實現Cloneable
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.