2009-02-08 16 views
50

Ho una domanda sui costruttori e sull'ereditarietà predefiniti in Java.Costruttori predefiniti ed ereditarietà in Java

In genere, se si scrive una classe e non si include alcun costruttore, Java fornisce automaticamente un costruttore predefinito (uno senza parametri), che inizializza tutte le variabili di istanza della classe (se presenti) con alcuni valori predefiniti (0, null o false). Se si scrive un costruttore, tuttavia, con alcuni parametri e non si scrive alcun costruttore predefinito, Java non fornisce un costruttore predefinito. La mia domanda è: qual è il caso delle classi, che ereditano da altre classi - se scrivo un costruttore con alcuni parametri al loro interno, ma non includo un costruttore predefinito, ereditano il costruttore predefinito della super classe?

+1

fa la necessità postale una modifica alla riga che presuppone che "Constructor inizializza tutte le variabili di istanza della classe (se presenti) con alcuni valori predefiniti (0, null o false)." ingannare il lettore? –

risposta

51

I costruttori non sono ereditati.

Inoltre, l'inizializzazione dei campi viene eseguita dalla macchina virtuale, non dal costruttore predefinito. Il costruttore predefinito invoca semplicemente il costruttore predefinito della superclasse e il costruttore predefinito di Object è vuoto. Il punto buono di questo design è che non c'è modo di accedere mai ai campi non inizializzati.

+1

Sì, ho appena capito questo, potyl sotto ha sottolineato questo. Ma come (e quando) i campi sono inizializzati allora? (per favore, vedi il mio commento sulla risposta del potyl). – user42155

+0

È il caso che quando creo l'oggetto, Java assegna automaticamente i valori predefiniti? Ma poi di nuovo, creiamo oggetti con costruttori, giusto? – user42155

+0

Sì, ci sono voluti un po 'per fare la ricerca w.r.t. inizializzazione. – starblue

10

A meno che non si usi super (...) un costruttore chiama il costruttore vuoto del suo genitore. Nota: lo fa su tutte le classi, anche su quelle che estendono l'oggetto.

Questo non sta ereditando, le sottoclassi non ottengono gli stessi costruttori con gli stessi argomenti. Tuttavia, puoi aggiungere costruttori che chiamano uno dei costruttori della super classe.

+0

Con "costruttore vuoto" si intende il costruttore predefinito, giusto? – user42155

+0

E se il genitore non ha un costruttore predefinito? – user42155

+0

Qui intendo un costruttore senza argomenti. In genere il costruttore predefinito è uno che non è definito affatto. È possibile definire un costruttore senza argomenti. –

3

Se si fornisce un costruttore, Java non genererà un costruttore vuoto predefinito. Quindi la tua classe derivata sarà in grado di chiamare il tuo costruttore.

Il costruttore predefinito non inizializza le variabili private ai valori predefiniti. La dimostrazione è che è possibile scrivere una classe che non ha un costruttore predefinito e ha i suoi membri privati ​​inizializzati su valori predefiniti. Ecco un esempio:

public class Test { 

    public String s; 
    public int i; 

    public Test(String s, int i) { 
     this.s = s; 
     this.i = i; 
    } 

    public Test(boolean b) { 
     // Empty on purpose! 
    } 

    public String toString() { 
     return "Test (s = " + this.s + ", i = " + this.i + ")"; 
    } 

    public static void main (String [] args) { 
     Test test_empty = new Test(true); 
     Test test_full = new Test("string", 42); 
     System.out.println("Test empty:" + test_empty); 
     System.out.println("Test full:" + test_full); 
    } 
} 
+0

Questo è interessante! Ho vissuto abbastanza a lungo con l'ipotesi che se non si inizializzano le variabili di istanza in un costruttore, Java lo fa nel costruttore predefinito. Quindi, in questo caso, come vengono inizializzate le variabili? – user42155

+0

Qui ho trovato un bell'articolo sull'inizializzazione in Java, rispondendo alla mia domanda: http://www.javaworld.com/javaworld/jw-03-1998/jw-03-initialization.html?page=1 – user42155

+0

Creazione di un oggetto l'istanza richiede che l'operatore "nuovo" allochi la memoria e invochi un costruttore (utilizzato per la logica iniziale). I nostri costruttori si occupano solo di quest'ultimo. Immagino che la prima parte si occupi dell'inizializzazione predefinita dei membri dei dati durante l'allocazione della memoria. – potyl

59
  1. Se non si fanno un costruttore, the default empty constructor is automatically created.

  2. Se un costruttore non richiama esplicitamente un super o questo costruttore come prima istruzione, a call to super() is automatically added.

Sempre.

+2

I collegamenti sono interrotti (grazie, Oracle), ecco i nuovi: http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.9 e http : //docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.8.7 – Stoffe

+1

@Stoffe: ho suggerito una modifica che fissa i collegamenti grazie ai tuoi commenti. Puoi guadagnare reputazione suggerendo delle modifiche, quindi perché non farlo in futuro? – Flimm

+0

Aggiungo che, nel caso 2, la chiamata a super non ha parametri. – LuxDie

1

Quando non si crea un costruttore, Java crea automaticamente un costruttore predefinito. Ma quando creiamo uno o più costruttori personalizzati con argomenti, Java non crea costruttori predefiniti. Se creiamo uno o più costruttori e vogliamo creare un oggetto senza alcun argomento di costruzione, dobbiamo dichiarare un costruttore vuoto.

+0

"... crea un oggetto senza alcun costruttore Dobbiamo dichiarare ..." => "... creare un oggetto senza alcun costrutto ** argomenti **, dobbiamo dichiarare ..." –

2

Thumb Rule è che la Sottoclasse deve chiamare qualsiasi costruttore dalla classe base. quindi se non hai il const predefinito, chiama quello esistente da sottoclasse.altri saggi implementare il const vuoto nella classe di base per evitare il problema di compilazione

6

La regola di base è una chiamata (o invocazione) per un costruttore deve essere la prima istruzione che JVM ha bisogno di eseguire,

Quindi, quando si ha una super classe con solo costruttore parametrizzato e nessun costruttore predefinito, e la classe base non ha chiamate esplicite al costruttore parametrizzato della super classe, JVM fornisce il super(); chiamata che genera un errore in quanto non esiste un costruttore predefinito per la super classe, quindi forniamo un costruttore predefinito nella super classe o chiamiamo esplicitamente il costruttore parametrico della super classe nel costruttore della classe base. quando diamo la chiamata esplicita, quindi JVM non si preoccupa di mettere la linea super(); come invocazione del costruttore dovrebbe essere la prima affermazione del metodo, che non può avvenire (a causa della nostra chiamata esplicita).

+0

penso che dovrebbe è buona norma mettere sempre il costruttore di default lì, se vuoi costruttori "sovraccarichi". – lwpro2

5

sezione 8.8.9 del linguaggio Java Specification spiega in dettaglio cosa sta succedendo:

Se una classe non contiene dichiarazioni costruttore, poi un costruttore di default è implicitamente dichiarata. La forma del costruttore predefinito per una classe superiore livello, classe membro, o una classe locale è la seguente:

  • il costruttore di default ha la stessa accessibilità come la classe (§6.6).
  • Il costruttore di default non ha parametri formali, se non in una classe di membro interno non privato, in cui il costruttore di default dichiara implicitamente una parametro formale che rappresenta l'istanza immediatamente racchiude della classe (§8.8.1, §15.9 . 2, § 15.9.3).
  • Il costruttore predefinito non ha clausole di derivazione.
  • Se la classe dichiarata è l'oggetto classe primordiale, il costruttore predefinito ha un corpo vuoto. In caso contrario, il costruttore predefinito semplicemente richiama il costruttore della superclasse senza argomenti.

Si può vedere che non c'è alcuna eredità succedendo qui: tutto ciò che devi fare è il "compilatore magico" con il costruttore di default implicitamente dichiarato. La specifica chiarisce anche che il costruttore predefinito viene aggiunto solo quando la classe non ha costruttori, il che significa che la risposta alla tua domanda è "no": una volta assegnato a una classe un costruttore, l'accesso al costruttore predefinito della sua la superclasse è persa.

+0

link di riferimento: https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.9 – cellepo

2

La risposta alla tua domanda è molto semplice. Implicitamente (invisibile), la prima affermazione in qualsiasi costruttore è 'super();' cioè la chiamata al costruttore di parametri senza super-classe, finché non la cambi esplicitamente in qualcosa come 'this();', 'this (int)', 'this (String)', 'super (int)', 'super (String) 'ecc. ' this(); ' è il costruttore della classe corrente.

0

Ci sarà errore di compilazione tempo ... perché compilatore cerca il difetto di costruzione che superclasse e se la sua non c'è ... la sua un errore ... e programma non Compile ...