2013-09-27 15 views
6

Diciamo che Class B estende class A e class A è Cloneable come segue:Java - abbattuti nel clone

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

Perché è legale per eseguire abbattuto da A a B nella riga successiva:

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

mentre il prossimo down cast è un errore in fase di esecuzione?

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

Grazie in anticipo!

+0

Vuoi dire 'B b = new B();' e 'A a = (A) b.clone();' per caso? – blalasaadri

+0

Ottima domanda su clone(), era una cosa che non riuscivo nemmeno a capire. – raiks

risposta

8

In definitiva, questo è usando Object.clone() creare l'oggetto - e che è garantito per creare un nuovo oggetto dello stesso tipo tempo di esecuzione come oggetto si chiama on:

Procedimento clone per la classe Object esegue una specifica operazione di clonazione. Innanzitutto, se la classe di questo oggetto non implementa l'interfaccia Cloneable, viene lanciato un CloneNotSupportedException. Si noti che tutti gli array sono considerati implementare l'interfaccia Cloneable e che il tipo restituito del metodo clone di un array di tipo T[] è T[] dove T è qualsiasi riferimento o tipo primitivo. Altrimenti, questo metodo crea una nuova istanza della classe di questo oggetto e inizializza tutti i suoi campi con esattamente il contenuto dei campi corrispondenti di questo oggetto, come se per assegnazione; i contenuti dei campi non sono essi stessi clonati. Pertanto, questo metodo esegue una "copia superficiale" di questo oggetto, non un'operazione di "copia profonda".

Quindi, se otteniamo una chiamata a clone() in esecuzione su un'istanza di B, poi super.clone() restituirà un B (o una sottoclasse) - in modo che il cast è valido.

Nel suo secondo caso, si sta creando un'istanza di appena A, che è non un'istanza di B, quindi il cast non riesce.

+0

Questo è il motivo per cui un'implementazione del metodo clone NON dovrebbe MAI creare direttamente la copia via new ma dovrebbe usare SEMPRE super.clone()! Altrimenti è impossibile sovrascrivere correttamente il clone nelle sottoclassi! – isnot2bad

+0

Grazie per la risposta dettagliata ... Quando ho eseguito il debug del codice, la prossima riga di codice: B a = (B) super.clone(); mi ha inviato a A.clone() che restituisce l'istanza di A..so non capisco come super.clone() restituisca una B? –

+2

@HeshamYassin: No, 'A.clone()' restituisce un riferimento che è * almeno * un 'A' - questo è ciò che è garantito dal cast di' A'. Ma in realtà * sarà * un 'B' (o una sottoclasse), perché stai clonando un'istanza di' B'. Osserva il valore di 'ac' nel debugger e vedrai che si tratta di un riferimento a un'istanza di' B'. –