clone()
方法是Java中用于复制对象的方法,它创建了一个与已存在对象相同类的新实例,并将所有字段复制到这个新实例中(即"浅拷贝")。此信息来自于维基百科。
你可能会对为什么它是浅拷贝感到困惑。实际上,clone()
方法确实会创建一个新实例并复制所有字段,但是如果这些字段本身是对象,则只会复制引用而不是对象本身。因此,在新实例中,这些引用指向的对象与原始对象中的引用指向的对象相同。这就是clone()
方法所做的全部,所以它被称为浅拷贝而不是深拷贝。希望解决你的疑问。
clone()
方法是Java中用于复制对象的方法,它创建了一个与已存在对象相同类的新实例,并将所有字段复制到这个新实例中(即"浅拷贝")。此信息来自于维基百科。
你可能会对为什么它是浅拷贝感到困惑。实际上,clone()
方法确实会创建一个新实例并复制所有字段,但是如果这些字段本身是对象,则只会复制引用而不是对象本身。因此,在新实例中,这些引用指向的对象与原始对象中的引用指向的对象相同。这就是clone()
方法所做的全部,所以它被称为浅拷贝而不是深拷贝。希望解决你的疑问。
默认的Object.clone()
确实是浅拷贝。然而,它的设计是除非您的对象实现了Cloneable
,否则会抛出CloneNotSupportedException
异常。
当您实现Cloneable
时,您应该重写clone()
以使其执行深拷贝,并调用所有可克隆字段上的clone()
方法。
clone
方法的其他人会期望它像描述的那样行为。当然,也有例外情况,比如对于通用容器(@jt's答案)。但总的来说,这是期望的行为。 - C. K. Young这是一个浅拷贝,因为它只复制了对其他对象的引用。假设我们有以下类:
class A {
B variable
A() {
variable = new B();
}
}
class B { }
现在我们来克隆一个A类实例:
A firstA = new A();
A secondA = firstA.clone();
firstA和secondA中的B实例将是相同的。您不会有B实例的副本。这就是为什么clone()被称为浅复制的原因。
您链接页面上的图表应该帮助您理解所有内容。
顺便提一下,我很惊讶没有人提到 Joshua Bloch关于Cloneable的观点
如果你读过我的书中关于克隆的部分,特别是在字里行间,你会知道我认为clone方法是有严重缺陷的。存在一些设计上的缺陷,其中最大的问题是Cloneable接口没有clone方法。这意味着它根本无法正常工作:将某物设置为可克隆并不能说明你能够对它进行什么操作。相反,它只是说明了它在内部可以做什么。它表示,如果通过反复调用super.clone最终调用Object的clone方法,那么这个方法将返回原始对象的一个字段副本。
clone()创建所有字段的副本。Java有原始类型和引用 - 当您克隆对象时,您会得到一个新对象,其中包含所有基本字段的副本(就像深层复制),但还会复制所有引用字段。因此,结果是您获得两个对象,它们拥有自己的原语副本和对相同对象的引用副本 - 原始对象和复制对象都将使用相同的对象。
有些对象不提供深复制。例如,ArrayList会克隆列表,但不会克隆列表中的元素。以下内容来自JavaDoc关于ArrayList的文档:
public Object clone()
Returns a shallow copy of this ArrayList instance. (The elements themselves are not copied.)
Object.clone()的默认实现是浅拷贝。对于具有大量基本字段或不可变字段的类型,此行为仍然很有用。您可以查看如何正确重写克隆方法?以了解如何正确地覆盖它。在调用super.clone()后,然后将结果对象转换,您可以根据需要进行更深层次的克隆。
随着类型上复杂、可变字段数量的增加,克隆的价值会逐渐降低。
clone
的作用是由选择支持 clone 的每个对象定义的。Object.clone 是受保护的,因此除非有人明确定义了它,否则没有对象允许 clone。
是的。
但首先你需要让你的类实现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);
}
}
输出:真