Java ordre de l'Initialisation et de l'Instanciation
Je suis en train d'essayer de reconstituer le processus d'Initialisation et d'Instanciation dans la JVM, mais le JLS est un peu obtus sur quelques détails, donc si quelqu'un aurait l'esprit de compensation de certains détails, il serait apprécié. C'est ce que j'ai pu découvrir jusqu'à présent.
Initialisation
-
De manière récursive Initialiser static final variables de la classe et des interfaces de compiler les constantes de temps.
-
Retour de la récurrence de traitement des blocs statiques et les champs statiques dans l'ordre textuel.
Instanciation
-
De manière récursive Initialiser final variables d'instance de la classe qui sont à la compilation des constantes de temps.
-
Retour de la récurrence de traitement des non-blocs statiques et les champs d'instance dans l'ordre textuel ajoutant à l'constructeurs de retour.
Bon, maintenant pour les questions.
-
interfaces sont traitées dans l'ordre de déclaration?
-
interfaces sont traitées dans une autre pile récursive?
a) si oui, avez-interfaces être traités avant ou après le super-classes?
b) si oui, suis-je correct en déduire que l'un ou l'autres (Interface ou de la super-classe) obtient sa non-constante à la compilation des champs initialisés avant les autres constantes de compilation.
-
Quel est le rôle d'appels de l'autre constructeur super() jouer dans ce processus?
-
Suis-je trompé dans mes conclusions?
-
Me manque tout les autres détails de la clé?
- Les Interfaces n'ont rien à initialiser. Sauf si vous êtes en utilisant le mot dans un autre mode que je suis habitué.
- Les Interfaces peuvent avoir public static final champs. Si ces champs sont des objets avec un initialiseur (par exemple
public static final ArrayList<String> someStrings = new ArrayList<>();
) alors que ce serait une partie de l'initialisation.
Vous devez vous connecter pour publier un commentaire.
Il est important de faire la distinction entre l'initialisation d'une classe, et l'initialisation d'un objet.
Initialisation De Classe
Une classe ou une interface est initialisé lors de la premier accès, en attribuant le temps de compilation champs constants, puis, de manière récursive l'initialisation de la super-classe (si ce n'est déjà initialisé), puis le traitement de la initialiseurs statiques (qui incluent les initialiseurs pour les champs statiques qui ne sont pas de compiler des constantes de temps).
Comme vous l'avez remarqué, l'initialisation d'une classe ne comprend pas, par elle-même, déclencher l'initialisation des interfaces qu'il implémente. Interfaces sont donc initialisé quand ils sont tout d'abord accessibles, généralement par la lecture d'un champ qui n'est pas une compilation constante de temps. Cet accès peut se produire lors de l'évaluation d'un initialiseur, provoquant un appel récursif à l'initialisation.
Il est également intéressant de noter que l'initialisation n'est pas déclenchée par accéder à des champs que sont la compilation des constantes de temps, que celles-ci sont évaluées à moment de la compilation:
L'Initialisation De L'Objet
Un objet est initialisé chaque fois qu'un nouvel objet est créé, généralement par l'évaluation de une création de l'instance de la classe expression. Ce produit comme suit:
Comme nous pouvons le voir dans l'étape 3, la présence d'un appel explicite à la super constructeur modifie simplement super-constructeur de la classe est appelée.
Qui suit est un exemple d'impression de l'ordre de chaque étape lors de la création de l'objet.
InstanceCreateStepTest.java:
Exécution:
Il suffit d'invoquer la méthode main, et de vérifier ensuite la sortie.
Conseils:
@PostConstruct
de ne pas être invoquée, sauf si vous l'appelez à l'intérieur de certaines conteneur, commeSpring-boot
, car il dépend de ces conteneurs pour mettre en œuvre l'annotation comme@PostConstruct
.