2013-09-27 4 views
6

Lassen Sie uns sagen, dass Class B erstreckt class A und class A klonbar ist wie folgt:Java - gesenkten in Klon

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; 
    } 
} 

Warum es legal ist, von A nach B in der nächsten Zeile auszuführen gesenkten:

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

während der nächste Downcast ist Laufzeitfehler?

Vielen Dank im Voraus!

+0

Meinst du 'B b = new B();' und 'A a = (A) b.clone();' zufällig? – blalasaadri

+0

Ausgezeichnete Frage zu Klon(), es war eine Sache, die ich auch nicht um den Kopf wickeln konnte. – raiks

Antwort

8

Letztendlich ist dies Object.clone() mit dem Objekt erstellen - und das ist garantiert, um ein neues Objekt des gleichen Ausführungszeit Typs wie das Objekt zu erstellen, es auf genannt:

Verfahren clone für Klasse Object führen eine spezifische Klonoperation. Wenn die Klasse dieses Objekts die Schnittstelle Cloneable nicht implementiert, wird zuerst CloneNotSupportedException ausgelöst. Beachten Sie, dass alle Arrays die Schnittstelle Cloneable implementieren und dass der Rückgabetyp der Clone-Methode eines Array-Typs T[]T[] ist, wobei T eine beliebige Referenz oder ein primitiver Typ ist. Andernfalls erstellt diese Methode eine neue Instanz der Klasse dieses Objekts und initialisiert alle ihre Felder mit genau dem Inhalt der entsprechenden Felder dieses Objekts, wie durch Zuweisung; Die Inhalte der Felder sind nicht selbst geklont. Daher führt dieses Verfahren eine "flache Kopie" dieses Objekts durch, keine "tiefe Kopie" -Operation.

Also, wenn wir auf einer Instanz ausgeführt bekommen von B einen Aufruf an clone() wird, dann super.clone() wird wieder eine B (oder eine Unterklasse) - so die Besetzung ist gültig.

In Ihrem zweiten Fall sind Sie eine Instanz nur A zu schaffen, die nicht eine Instanz von B ist, so dass die Umwandlung fehlschlägt.

+0

Das ist der Grund, warum eine Klon-Methodenimplementierung NIEMALS direkt die Kopie über new erstellen sollte, sondern stattdessen super.clone() verwenden sollte! Andernfalls ist es unmöglich, Klone in Unterklassen korrekt zu überschreiben! – isnot2bad

+0

Danke für die detaillierte Antwort ... Als ich den Code debuggte, die nächste Codezeile: B a = (B) super.clone(); schickte mich an A.clone(), die Instanz von A..so ich verstehe nicht, wie super.clone() ein B zurückgeben? –

+2

@HeshamYassin: Nein, 'A.clone()' gibt eine Referenz zurück, die * mindestens * ein 'A' ist - das ist garantiert durch die Besetzung von' A'. Aber es wird * eigentlich * ein 'B' (oder eine Unterklasse) sein, weil du eine Instanz von' B' klonst. Sehen Sie sich den Wert von ac im Debugger an, und Sie werden sehen, dass es sich um eine Instanz von B handelt. –