java中的clone()
是浅层副本吗?
最终这会到达clone() 对象的方法(最上面的 class),它创建一个新实例 与对象相同的类和 将所有字段复制到新字段 实例(“浅拷贝”)。
我是从wikipedia读到的。
我不明白为什么它是浅拷贝。 clone()
将创建一个包含所有字段的新实例。这只是一个很深的副本吗?困惑。需要一些解释。
答案 0 :(得分:16)
默认Object.clone()
确实是浅色副本。但是,它被设计为抛出CloneNotSupportedException
,除非您的对象实现Cloneable
。
当您实施Cloneable
时,您应该覆盖clone()
以使其执行深层复制,方法是在所有可克隆的字段上调用clone()
答案 1 :(得分:5)
顺便说一句,我很惊讶没人提到Joshua Bloch's views on Cloneable
如果您已阅读有关克隆的项目 在我的书中,特别是如果你读 在这些线之间,你会知道的 我认为克隆已经深受打击。那里 是一些设计缺陷,最大的 这是Cloneable接口 没有克隆方法。然后 意味着它根本不起作用:制作 克隆无法说的东西 关于你可以做些什么的任何事情 它。相反,它说了些什么 它在内部可以做什么。它说 如果通过调用super.clone 反复它最终调用对象的 克隆方法,此方法将返回 原件的现场副本。
答案 2 :(得分:4)
clone()创建所有字段的副本。 Java有原始类型和refences - 当您克隆对象时,您将获得一个包含所有原始字段副本的新对象(类似于深层复制),但您还拥有所有引用字段的副本。因此,在结果中,您将获得两个对象,这些对象具有原始副本和对相同对象的引用副本 - 原始对象和复制对象都将使用相同的对象。
答案 3 :(得分:4)
它是浅拷贝,因为它只复制对其他对象的引用。假设我们有这些课程:
class A {
B variable
A() {
variable = new B();
}
}
class B { }
现在我们克隆一个A:
的实例A firstA = new A();
A secondA = firstA.clone();
firstA和secondA中的B实例将是相同的。您将没有B实例的副本。这就是为什么说clone()做浅拷贝的原因。
您链接的页面上的图表可以帮助您理解所有这些。
答案 4 :(得分:3)
某些对象不提供深层复制。例如,ArrayList将克隆列表,但不克隆列表中的元素。以下是来自JavaDoc的ArrayList:
public Object clone() Returns a shallow copy of this ArrayList instance. (The elements themselves are not copied.)
答案 5 :(得分:2)
Object.clone()的默认实现是浅拷贝。对于具有大量原始字段或不可变字段的类型,此行为仍然有用。您可以查看How to properly override clone method?以了解如何正确覆盖它。在调用super.clone()之后,然后转换生成的对象,然后可以根据需要进行更深层次的克隆。
隐含地,随着您的类型上复杂的可变字段数量的增加,克隆的价值会减少。
答案 6 :(得分:1)
为每个选择支持克隆的对象定义了clone
的作用。 Object.clone受到保护,因此除非有人专门定义了对象,否则没有对象允许克隆。
答案 7 :(得分:0)
是
但首先你需要你的类实现Cloneable并抛出异常
class A implements Cloneable{
public int y;
public B b;
public A(){
b = new B();
}
public static void main(String[] args) throws CloneNotSupportedException{
A a = new A();
A a2 = (A) a.clone();
System.out.print(a.b==a2.b);
}
}
输出:true