2013-03-05 97 views
3

此克隆示例让我困惑。我不明白前两个输出可以如何:111和222,而不是:222和222. 这不是“a2 =(A)a1.clone();”意味着a2和a1一样吗?Java克隆继承示例

代码:

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

值获得一个clone()操作跨越复制,但你最终获得2个不同的对象,只是他们有相同的价值观。

a2 = (A) a1.clone() 

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

2

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

当你做到这一点

a1=(A)a2.clone(); 

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

2

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

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

从文档,Object.clone

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

x.clone() != x

将为真。

从同一个文档继续:

这个方法创建此对象的类的一个新实例,并 初始化所有的字段与此对象的 相应字段的确切内容,如如果通过转让;该字段的内容 本身并不克隆。因此,此方法执行此对象的“浅拷贝”的 ,而不是“深拷贝”操作。

0

在您所提供的步骤顺序的代码是像下面。

  1. 复制的对象以Ai值作为111所以用相同值的克隆对象即创建111
  2. 然后您将i的值更改为原始对象的222,以便克隆对象的值不会更新,如克隆原始类型时创建具有相同值的新实例(当对象被克隆时)。