2013-09-27 134 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'實例的引用。 –