ProgrammationDéveloppeur Java Middle/Senior

Qu'est-ce que l'ordre d'initialisation des classes en Java, comment cela fonctionne-t-il et quelles peuvent être les conséquences d'une mauvaise compréhension de l'ordre d'initialisation des membres statiques et non statiques ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

L'ordre d'initialisation des classes en Java (order of class initialization) définit dans quel ordre les champs, les blocs et les constructeurs sont initialisés. En résumé :

  1. Les champs statiques et les initialiseurs statiques sont exécutés dans l'ordre où ils apparaissent dans la classe, lorsque la classe est chargée par la JVM (une seule fois par classe).
  2. Les champs non statiques et les initialiseurs sont exécutés dans l'ordre où ils apparaissent CHAQUE fois qu'une instance est créée, avant l'appel du constructeur.
  3. Le constructeur est exécuté après l'initialisation de tous les champs et blocs.

Exemple

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() -> quel ordre ?

La sortie sera :

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

D'abord les blocs statiques des parents, puis les blocs statiques des enfants, puis les blocs non statiques et les constructeurs dans l'ordre de l'héritage.

Question piégeuse.

Question : Quand les initialiseurs statiques seront-ils exécutés dans la classe :

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

— lors de la création de la première instance ou lors de la première utilisation de n'importe quelle méthode/champ statique ?

Réponse : L'initiateur statique est exécuté lors du premier accès à la classe, y compris l'accès à n'importe quel membre statique (méthode/champ), et pas seulement lors de la création d'une instance.

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet.


Histoire

Dans une application bancaire, un pool de connexions statique était initialisé dans un bloc statique, mais en raison d'un accès à une méthode statique avant la création de la première instance, la connexion n'avait pas encore été établie. Cela a conduit à un NullPointerException sous charge.


Histoire

Le service de journalisation dépendait d'un champ non statique, qui était initialisé après l'appel au constructeur de la classe parente. Les journaux étaient écrits dans un logger null, et des messages d'erreur importants ont été perdus.


Histoire

Lors de l'ajout d'un nouveau champ avec une valeur par défaut, le développeur l'a placé après le bloc d'initialisation : le bloc a essayé d'utiliser un champ qui n'avait pas encore été initialisé, ce qui a conduit à des erreurs lors du démarrage de l'application et à une recherche difficile de la cause.