![](/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.