ProgrammazioneSviluppatore Java Middle/Senior

Che cos'è l'ordine di inizializzazione della classe in Java, come funziona e a cosa può portare una comprensione errata dell'ordine di inizializzazione dei membri statici e non statici?

Supera i colloqui con l'assistente IA Hintsage

Risposta.

L'ordine di inizializzazione della classe in Java (class initialization order) definisce in quale sequenza vengono inizializzati i campi, i blocchi e i costruttori. In breve:

  1. I campi statici e gli inizializzatori statici vengono eseguiti nell'ordine in cui appaiono nella classe, quando la classe viene caricata dalla JVM (una sola volta per classe).
  2. I campi non statici e gli inizializzatori vengono eseguiti nell'ordine in cui appaiono OGNI volta che si crea un'istanza, prima della chiamata al costruttore.
  3. Il costruttore viene eseguito dopo l'inizializzazione di tutti i campi e i blocchi.

Esempio

class Parent { static { System.out.println("Parent static"); } { System.out.println("Parent init"); } Parent() { System.out.println("Parent constructor"); } } class Child extends Parent { static { System.out.println("Child static"); } { System.out.println("Child init"); } Child() { System.out.println("Child constructor"); } } // new Child() -> che ordine?

L'output sarà:

  1. Parent static
  2. Child static
  3. Parent init
  4. Parent constructor
  5. Child init
  6. Child constructor

Prima i blocchi statici dei genitori, poi i blocchi statici dei figli, poi i blocchi non statici e i costruttori in ordine di ereditarietà.

Domanda trabocchetto.

Domanda: Quando verranno eseguiti gli inizializzatori statici nella classe:

class Ex {
    static { System.out.println("static"); }
}

— alla creazione della prima istanza o al primo utilizzo di qualsiasi metodo/campo statico?

Risposta: L'inizializzatore statico viene eseguito al primo accesso alla classe, inclusi l'accesso a qualsiasi membro statico (metodo/campo), e non solo alla creazione di istanze.

Esempi di errori reali a causa della mancanza di conoscenza delle sottigliezze dell'argomento.


Storia

In un'applicazione bancaria, il pool di connessioni statiche veniva inizializzato in un blocco statico, ma a causa di una chiamata a un metodo statico prima della creazione della prima istanza, la connessione non era ancora stata creata. Questo ha portato a un NullPointerException durante il carico.


Storia

Il servizio di logging dipendeva da un campo non statico, che veniva inizializzato dopo la chiamata al costruttore della classe genitore. I log venivano registrati in un logger nullo, causando la perdita di importanti messaggi di errore.


Storia

Durante l'aggiunta di un nuovo campo con un valore iniziale, lo sviluppatore lo aveva posizionato dopo il blocco di inizializzazione: il blocco tentava di utilizzare un campo non ancora inizializzato, causando errori durante l'avvio dell'applicazione e una difficile individuazione della causa.