Ordre d'initialisation des classes en Java

Lors de l'instanciation en Java, le mécanisme d'initialisation suit un protocole précis entre les classes parentes et leurs dérivées. Ce processus s'exécute selon la séquence suivente :

  • Initialisation des champs statiques de la classe parente
  • Exécution des blocs statiques parentaux
  • Initialisation des champs statiques de la classe enfant
  • Exécution des blocs statiques enfant
  • Initialisation des champs d'instance parentaux
  • Exécution des blocs d'instance parentaux
  • Appel du constructeur parent
  • Initialisation des champs d'instance enfant
  • Exécution des blocs d'instance enfant
  • Appel du constructeur enfant

Illustration avec une implémentation modifiée :

public class Parent {
    static {
        System.out.println("Bloc statique Parent");
    }
    
    {
        System.out.println("Bloc d'instance Parent");
    }
    
    public Parent() {
        System.out.println("Constructeur Parent");
    }
}
public class Enfant extends Parent {
    private int rayon = 1;
    
    static {
        System.out.println("Bloc statique Enfant");
    }
    
    {
        System.out.println("Bloc d'instance Enfant");
    }
    
    public Enfant(int valeur) {
        rayon = valeur;
        System.out.println("Constructeur Enfant");
    }
    
    public static void main(String[] args) {
        new Enfant(5);
    }
}

Sortie obtenue :

Bloc statique Parent
Bloc statique Enfant
Bloc d'instance Parent
Constructeur Parent
Bloc d'instance Enfant
Constructeur Enfant

Une observation critique émerge lors de l'appel de méthodes surchargées pendant l'initialisation. En modifiant les blocs d'instance pour invoquer une méthode virtuelle :

public class Parent {
    static {
        System.out.println("Bloc statique Parent");
    }
    
    {
        System.out.println("Bloc d'instance Parent");
        afficher();
    }
    
    public Parent() {
        System.out.println("Constructeur Parent");
    }
    
    public void afficher() {
        System.out.println("Affichage Parent");
    }
}
public class Enfant extends Parent {
    private int rayon = 1;
    
    static {
        System.out.println("Bloc statique Enfant");
    }
    
    {
        System.out.println("Bloc d'instance Enfant");
    }
    
    public Enfant(int valeur) {
        rayon = valeur;
        System.out.println("Constructeur Enfant");
        afficher();
    }
    
    @Override
    public void afficher() {
        System.out.println("Affichage Enfant " + rayon);
    }
}

Résultat d'exécution :

Bloc statique Parent
Bloc statique Enfant
Bloc d'instance Parent
Affichage Enfant 0
Constructeur Parent
Bloc d'instance Enfant
Constructeur Enfant
Affichage Enfant 5

Ce comportement révèle que les méthodes virtuelles sont résolues dynamiquement dès le premier appel, même lorsque les champs de l'instance enfant n'ont pas encore été initialisés. L'ordre complet s'ajuste ainsi :

Méthodes virtuelles résolues → Champs statiques parentaux → Blocs statiques parentaux → Champs statiques enfant → Blocs statiques enfant → Champs d'instance parentaux → Blocs d'instance parentaux → Constructeur parent → Champs d'insatnce enfant → Blocs d'instance enfant → Constructeur enfant

Étiquettes: Java Programmation orientée objet Initialisation de classe Surcharge de méthode constructeurs

Publié le 6 août à 14h56