Connaissez-vous bien l'instanciation ?
Ce court billet va vous présenter quelles instructions sont exécutées dans vos classes Java, lorsque que vous en réclamez une instance.
Que va-t-on tester ?
Une classe Java, que l’on souhaite pouvoir instancier, peut disposer :
- d’une et unique portion de code
static; - d’une et unique portion de code d’instance (si vous ne savez pas ce que c’est, l’exemple arrive ci-après …) ;
- d’un ou plusieurs constructeurs.
Pour être un peu plus complet, une classe peut aussi contenir les éléments suivants, mais cet article ne traite pas de leur instanciation :
- une ou plusieurs classes embarquées statiques ;
- une ou plusieurs classes embarquées d’instance.
L’idée est donc de tester l’enchainement des lignes de codes lors du mécanisme d’instanciation, pourtant largement utilisé par tous !
Le jeu de test
Nous avons à notre disposition deux classes : Root et Child.
Comme leur nom l’indique : Child hérite de Root, ce qui n’est pas toujours évident quand on implémente l’interface Hallyday (humour …).
Pour faire plaisir à J-Jacques (qui cherche encore une enum dans cet article) et Mika, un petit diagramme UML :

On peut difficilement faire plus simple …
Voici le code source de la classe Root
public class Root
{
// <1>
static
{
System.out.printf("static block : %s %n", Root.class);
}
// <2>
{
System.out.printf("Root instance block : %s %n",this.getClass());
}
// <3>
public Root()
{
System.out.println("Root noargs constructor");
}
}
On a rarement fait plus concis, mais cette classe n’est quand même pas banale, car elle dispose :
- d’une portion de code statique de classe, déclenchée lors du chargement de la classe par le ClassLoader, à son premier appel ;
- d’une portion de code d’instance, déclenchée avant les constructeurs de la classe ;
- d’un constructeur sans argument (no comment, j’espère que vous savez quand même ce qu’est un constructeur …)
Et voici le code source de la classe Child qui est implémentée sur le même principe que la classe Root dont elle hérite.
public class Child extends Root
{
static
{
System.out.printf("static block : %s %n", Child.class);
}
{
System.out.printf("Child instance block : %s %n",this.getClass());
}
public Child()
{
System.out.println("Child noargs constructor");
}
}
Seuls les différents affichages changent afin de pouvoir différencier l’exécution de telle ou telle portion de code.
Au résultat de l’instanciation
Quand on instancie la classe avec le code suivant : Child child = new Child(), voici le résultat :
static block : class fr.fxjavadevblog.articles.Root
static block : class fr.fxjavadevblog.articles.Child
Root instance block : class fr.fxjavadevblog.articles.Child
Root noargs constructor
Child instance block : class fr.fxjavadevblog.articles.Child
Child noargs constructor
Commentaires :
- sans surprise, le bloc
staticdeRootest exécuté en premier. - puis vient le tour du bloc
staticdeChild: rien d’étonnant pour le moment. - puis c’est le bloc d’instance de
Rootalors quethis.getClass()retourne bienChild. Et oui ! L’instance concrète courante est bien de typeChildbien que le code soit présent dans la classeRoot. - le constructeur sans argument de
Rootest déclenché. C’est intéressant, on n’est toujours pas passé dans le bloc d’instance deChild. Pour mémoire, le constructeur par défaut d’une classe mère est toujours appelé implicitement quand aucun autre constructeursuper(args...)n’est invoqué de manière explicite. - le voilà maintenant exécuté notre bloc d’instance de
Child, intercallé donc entre le constructeur sans argument deRootet son propre constructeur. - Enfin, pour terminer, le constructeur sans argument de
Childferme la marche … Il était temps !
“Etonnant non” ? Pierre Desprogres, Dix minutes nécessaires de M. Cyclopède.


