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:
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à:
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: 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.
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.