Java 为什么在实现clone方法时返回super.clone()而不是this clone()
假设我想克隆一个对象,那么为什么我们总是返回Java 为什么在实现clone方法时返回super.clone()而不是this clone(),java,Java,假设我想克隆一个对象,那么为什么我们总是返回super.clone()。如果我想克隆一个对象,那么我想这就是我想克隆的对象。我是克隆的初学者。超类clone方法应该是object.clone(),或者它应该(最终)将1委托给object.clone()。这是一个“神奇”的方法,它知道如何创建当前实例的实际类的新实例 当然,如果您尝试像这样实现克隆: public abstract class Shape implements Cloneable { private String id;
super.clone()
。如果我想克隆一个对象,那么我想这就是我想克隆的对象。我是克隆的初学者。超类clone
方法应该是object.clone()
,或者它应该(最终)将1委托给object.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;
}
}
您将创建一个递归循环,该循环将以stackoverflowerrror
快速结束
1-如果
super.clone()
最终没有委托给Object.clone()
,则它将无法克隆由Shape
及其具体子类型定义的字段值
请注意,在这个特定示例中,
clone()
可以简化为:
public Object clone() {
return clone();
}
Shape
类将Object
作为其超类,Object.clone()
将抛出CloneNotSupportedException
的唯一情况是,如果实际类没有实现Cloneable
接口。但是Shape
本身会这样做
事实上,clone()
的所有声明实际上是为了增加受保护的版本的可见性对象中的
对象
API。无论您使用的是super
还是this
,被解除引用的对象都是相同的。但是,由于您使用this.clone()
覆盖clone
方法,因此会导致(无限)递归。使用super.clone()
确保调用超类的克隆
实现
请注意,Object.clone
复制整个对象,而不考虑实际类型
重写该方法时需要注意的唯一事项是:
- 增加对
公共的可见性(如果需要)
- 复制未被
super.clone()
下面的示例显示了克隆对象的常用方法
public Object clone() {
return 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) + '}';
}
}
将导致数组相同。在您的示例中super.clone()
指的是Object.clone()
,其JavaDoc状态为:
否则,此方法将创建此对象类的新实例,并使用此对象对应字段的内容初始化其所有字段,就像通过赋值一样;字段的内容本身不会被克隆。因此,此方法将执行此对象的“浅拷贝”而不是“深拷贝”操作
这意味着,如果浅拷贝就足够了,那么使用super.clone()
就足够了。覆盖在这里有两个用途:
- 将
clone()
公开(Object.clone()
受保护)
- 通过打印stacktrace并返回
null
,处理子类不能优雅地实现Cloneable
的情况
您可以通过适当的示例找到解释。这个.clone()
是简单的递归。您将得到一个堆栈溢出错误超级.clone();
与构造函数中的超级()
非常相似。克隆方法必须链接。对象.clone()
很神奇,但是在此上下文中,super
可能不是对象
是的。你是对的。(我正在更正…)但是,如果super.clone()
没有委托给Object.clone())
此实现不起作用!@AndrewTobilko-在本例中,我们知道Shape
的超类型是Object
。请查看它是如何声明的。
clone.numbers = this.numbers.clone();