2013-09-27 67 views
6

低垂让我们说Class B延伸class Aclass A是可复制如下:爪哇 - 克隆

public class A implements Cloneable { 
    public Object clone() throws CloneNotSupportedException { 
     A ac = (A) super.clone(); 
     return ac; 
    } 
} 

public class B extends A { 
    public Object clone() throws CloneNotSupportedException { 
     B a = (B) super.clone(); 
     return a; 
    } 
} 

为什么它是合法的从A到B的下一行进行垂头丧气:

B a = (B) super.clone(); // (super of B is A) 

而下一个下降是运行时错误?

A a = new A(); 
B b = (B) a.clone(); 

在此先感谢!

+0

你的意思是'B b = new B();'和'A a =(A)b.clone();'有没有机会? – blalasaadri

+0

有关克隆()的优秀问题,这也是我无法包裹头部的问题。 – raiks

回答

8

归根结底,这是使用Object.clone()创建对象 - 这保证创建相同的执行时类型为对象的新对象,它被称为上:

方法cloneObject执行一个特定的克隆操作。首先,如果该对象的类没有实现接口Cloneable,则引发CloneNotSupportedException。请注意,所有阵列都被视为实现接口Cloneable,并且阵列类型T[]的克隆方法的返回类型为T[],其中T是任何引用或原始类型。否则,此方法创建该对象的类的新实例,并使用该对象的相应字段的内容来初始化其所有字段,就像通过赋值一样;这些字段的内容本身并不克隆。因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作。

所以,如果我们得到的B一个实例正在执行clone()一个电话,然后super.clone()将返回一个B(或子类) - 这样的转换是有效的。

在你的第二个情况,你要创建的只是A一个实例,这是B一个实例,因此转换失败。

+0

这就是克隆方法实现不应该直接通过new创建副本的原因,但应始终使用super.clone()来代替!否则,不可能在子类中正确覆盖克隆! – isnot2bad

+0

感谢您的详细解答...当我调试代码时,下一个代码行: B a =(B)super.clone(); 送我到A.clone(),它返回A..so的实例,所以我不明白super.clone()如何返回一个B? –

+2

@HeshamYassin:不,'A.clone()'返回一个引用,它至少是一个'A' - 这就是演员保证'A'的保证。但它会*实际上是'B'(或一个子类),因为你正在克隆'B'的一个实例。在调试器中查看'ac'的值,你会发现它是对'B'实例的引用。 –