2012-03-28 12 views
6

Ecco il codice, ho definito due classe denominata Padre e del Figlio, e li creo nella funzione principale:Qual è l'ordine dei costruttori in questo codice Java?

public class Test { 
    public static void main(String[] args) { 
     Father father = new Son(); 
    } 
} 

class Father { 
    private String name = "father"; 
    public Father() { 
     who(); 
     tell(name); 
    } 
    public void who() { 
     System.out.println("this is father"); 
    } 
    public void tell(String name) { 
     System.out.println("this is " + name); 
    } 
} 

class Son extends Father { 
    private String name = "son"; 
    public Son() { 
     who(); 
     tell(name); 
    } 
    public void who() { 
     System.out.println("this is son"); 
    } 
    public void tell(String name) { 
     System.out.println("this is " + name); 
    } 
} 

e ho avuto l'output come questo:

this is son 
this is father 
this is son 
this is son 

ma non ci riesco capire come è successo? Qualcuno può dirmi perché?

+5

Lezione impara: non chiamare metodi da costruttori che possono essere sovrascritti. – Thilo

+2

un'altra lezione da imparare è che dovresti sempre provare a creare messaggi di "debug" che non possono essere interpretati erroneamente: cambierei i tuoi metodi in qualcosa come "System.out.println (" Son.who() "); ',' System.out.println ("Son.tell (" + name + ")"); ',' System.out.println ("Father.who()"); 'e' System.out. println ("Padre.tella (" + nome + ")"); ' –

risposta

9
  1. Cominciamo con il costruttore di Son.

    public Son() { 
        super(); // implied 
        who(); 
        tell(name); 
    } 
    
  2. Il costruttore del padre è chiamato.

    public Father() { 
        who(); 
        tell(name); 
    } 
    
  3. Perché who() viene sovrascritto dal Son, la versione 's la Son sarà chiamato, la stampa "questo è il figlio".

  4. tell() è anche sovrascritto ma il valore passato è Father.name, stampa "questo è padre".

  5. Infine, i who() e tell(name) chiamate all'interno costruttore 's Son saranno resi stampa 'questo è figlio' e 'questo è il figlio', rispettivamente.

3

Quando si crea l'istanza Son, viene chiamato il costruttore della classe genitore (ad esempio Father()); qui viene chiamato il metodo who(), ma è la versione sostituita dichiarata in Son, quindi ecco la prima riga (dove la stringa è codificata nel metodo).

La seconda linea viene dal tell(name) all'interno Father(), dove tell() viene sostituita ma name == "father" la chiamata viene dall'interno costruttore Father s', e name è un campo di classe Fatherprivate.

Il controllo torna al costruttore Son() e le ultime due righe provengono direttamente dal costruttore della classe Son.

2

Father() viene chiamato prima dello Son(). Il costruttore di superclassi predefinito è chiamato implicitamente, non abbiamo bisogno di una dichiarazione super() qui.

E who() all'interno del costruttore di Father() chiama il metodo di priorità.

5

Ecco ciò che viene chiamato:

new Son() 
=> 
    Son._init 
    => first every constructor calls super() 
     Father._init 
     Object._init 
     who() => is overridden, so prints "son" 
     tell(name) => name is private, so cannot be overridden => "father" 
    who() => "son" 
    tell(name) => "son" 

lezioni da imparare:

  • campi e metodi privati ​​sono privati. Non può essere ignorato.
  • Non chiamare metodi da costruttori che possono essere sovrascritti. Questo può chiamare metodi su stato di classe half-initialized (non accade nel tuo caso, però).
0

Il codice sopra riportato è di tipo Bad Style (TM). ;-)

Che cosa succede è: non esiste un'istanza padre, solo un'istanza Figlio. (Tuttavia, è compatibile con il padre).

Il costruttore Figlio chiama il costruttore Padre. Quest'ultimo chiama i metodi sovrascritti (!), Quindi Padre. Chi e Padre non si chiamano mai! I metodi sottoposti a override sono chiamati prima (!) Il costruttore del Son era finito.

Le mie raccomandazioni:

  1. Se si chiama un metodo in un costruttore, renderla definitiva. O rendere l'intera classe finale. Oppure rendere il metodo chiamato privato almeno.
  2. Non sovrascrivere mai un metodo chiamato in un costruttore.
  3. Se devi violare i consigli sopra riportati, scrivi commenti esaustivi sul motivo per cui l'hai fatto e su cosa ti aspetti che accada. Scrivi un test unitario per assicurarti che le tue supposizioni siano valide.
Problemi correlati