在java浅拷贝中是clone()吗?

时间:2011-03-11 22:56:31

标签: java deep-copy shallow-copy

java中的clone()是浅层副本吗?

  

最终这会到达clone()   对象的方法(最上面的   class),它创建一个新实例   与对象相同的类和   将所有字段复制到新字段   实例(“浅拷贝”)。

我是从wikipedia读到的。

我不明白为什么它是浅拷贝。 clone()将创建一个包含所有字段的新实例。这只是一个很深的副本吗?困惑。需要一些解释。

8 个答案:

答案 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