3

这个克隆示例让我感到困惑。我不明白前两个输出如何是:111 和 222 而不是:222 和 222。这不是“a2 = (A) a1.clone();”吗?行意味着 a2 变得与 a1 相同?

代码:

public class Main {

    public static void main(String[] args) {
    A a1 = new A();
    A a2;
    B b1 = new B();
    B b2;

    a2 = (A) a1.clone();
    a2.setI(222);

    // Why the different output?
    System.out.println("a1 = " + a1 + " a1.i " + a1.getI()); // i = 111
    System.out.println("a2 = " + a2 + " a2.i " + a2.getI()); // i = 222

    b2 = (B) b1.clone();

    b2.setI(888); 
    b2.setJ(999); 

    System.out.println("b1 = " + b1 + " b1.i " + b1.getI() + " b1.j " +      b1.getJ());
    System.out.println("b2 = " + b2 + " b2.i " + b2.getI() + " b2.j " + b2.getJ()); 
}
}

public class A implements Cloneable {
    private int i = 111;
    @Override
    public Object clone() {
        try {
            A a = (A) super.clone();
            return a;
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }
    public int getI() {
        return i;
    }

    public void setI(int i) {
        this.i = i;
        }
    }

    public class B extends A {
    private int j = 222;

    @Override
    public Object clone() {  
        Object o = super.clone();               
        B b = (B) o;
        return b;
    }

    public int getJ() {
        return j;
    }

    public void setJ(int j) {
        this.j = j;
    }
}
4

5 回答 5

5

这些值在clone()操作中被复制,但最终得到 2 个不同的对象,只是它们具有相同的值。

a2 = (A) a1.clone()

创建一个新对象,完全独立于 a1。但是 a1 的内部状态已经复制到 a2 中。因此,更改 a2 对 a1 没有影响(如果克隆正确!)

于 2013-03-05T16:31:19.197 回答
2

不,它们不再指向同一个对象,因此值的变化a2不会影响a1对象。这就是clone()您获得对象的相同但不同副本的概念。

当你这样做时

a1=(A)a2.clone();

你得到一个全新的对象,独立于从中复制它的对象。

于 2013-03-05T16:33:34.260 回答
2

克隆只制作对象的“浅”副本,这意味着复制原始值和对象引用。你想要的(我假设)是一个“深层”副本,其中引用的对象本身被克隆。一些最流行的方法来做到这一点:

  • Java 深度克隆库
  • 序列化对象,然后反序列化它(警告:这很慢!)
  • clone()在所有引用对象中实现,并clone()在引用对象的clone()方法中调用这些对象。您也可以以类似的方式使用复制构造函数。
于 2013-03-05T16:38:09.743 回答
0

从文档中,Object.clone

创建并返回此对象的副本。“复制”的确切含义可能取决于对象的类别。一般意图是,对于任何对象 x,表达式:

x.clone() != x

将是真的。

继续同一个文档:

此方法创建此对象的类的新实例,并使用此对象的相应字段的内容来初始化其所有字段,就像通过赋值一样;字段的内容本身不会被克隆。因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作。

于 2013-03-05T16:41:39.780 回答
0

在您提供的代码中,步骤顺序如下所示。

  1. 克隆A具有i值的对象,111以便创建具有相同值的克隆对象 ie 111
  2. Then you changed the value of i to 222 for the original object so the value of cloned object is not updated as in cloning for primitive types new instances with same value (when the object is cloned) is created.
于 2016-04-08T05:16:02.333 回答