Java克隆继承示例

时间:2013-03-05 16:29:06

标签: java

这个克隆示例让我很困惑。我不明白前两个输出是怎样的:111和222而不是:222和222。 这不是“a2 =(A)a1.clone();” line是指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;
    }
}

5 个答案:

答案 0 :(得分:5)

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

a2 = (A) a1.clone()

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

答案 1 :(得分:2)

不,他们不再指向同一个对象,因此a2的值更改不会影响a1对象。这就是clone()的概念,你得到的是对象的相同但不同的副本。

当你这样做时

a1=(A)a2.clone();

你得到一个全新的对象,与复制它的对象无关。

答案 2 :(得分:2)

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

  • Java Deep Cloning Library
  • 序列化对象,然后对其进行反序列化(警告:这很慢!)
  • 在所有引用的对象中实现clone(),并在引用对象的clone()方法中对这些对象调用clone()。您也可以以类似的方式使用复制构造函数。

答案 3 :(得分:0)

从文档中Object.clone

  

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

x.clone() != x

  

将是真的。

继续使用同一份文件:

  

此方法创建此对象的类的新实例   准确地初始化其所有字段的内容   该对象的相应字段,好像通过赋值;内容   这些田地本身没有克隆。因此,该方法执行a   这个对象的“浅拷贝”,而不是“深拷贝”操作。

答案 4 :(得分:0)

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

  1. A的对象克隆为i 111,以便创建具有相同值的克隆对象,即111
  2. 然后您将原始对象的i值更改为222,因此克隆对象的值不会更新,就像克隆原始类型具有相同值的新实例一样(克隆对象时) )已创建。