Ordre final d'initialisation de champ de Java
j'ai essayé de comprendre le comportement de l'ordre d'initialisation lorsque les champs statiques sont initialisés avec une référence au même objet de classe enveloppant.
public class Test {
static final Test t=new Test();
static int a=5;
Test(){
System.out.println("a="+a);
}
public static void main(String[] args) {
new Test();
}
}
sortie du morceau de code ci-dessus est:
a=0
a=5
si je modifie la variable a
en autre chose que static
:
static final a=5;
a=5;
final a=5;
la sortie est:
a=5
a=5
Pourquoi ce comportement?
notez que la sortie est a=5 & a=5
même si les deux t & a
sont déclarés comme static final
auquel cas t
précède la déclaration de a
4 réponses
les membres finals statiques sont initialisés avant les autres membres statiques.
non finale, les membres statiques sont initialisés dans l'ordre d'apparition
donc, dans votre premier cas :
static Test t=new Test();
static int a=5;
le constructeur est d'abord appelé avant que a
ne soit initialisé, donc a=0
est affiché.
dans le deuxième cas, static final a
est initialisé avant t
, donc a=5
est s'affiche lorsque la première instance de Test
est créée. Lorsque a
n'est pas statique, elle est initialisée avant l'exécution du constructeur, à nouveau a=5
est affiché.
concernant l'édition dans votre question.
en regardant la section 12.4.2 du JLS :
- ensuite, initialiser les variables de classe finales et les champs d'interfaces dont les valeurs sont des expressions de constante de temps de compilation (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
...
- ensuite, exécutez soit la variable de classe initializers et les initialisateurs statiques de la classe, soit les initialisateurs de champ de l'interface, dans l'ordre textuel, comme s'ils étaient un seul bloc.
vous voyez que les variables de classe finale (c.-à-d. statique final) sont initialisés avant le reste des variables statiques seulement si leurs valeurs sont le temps de compilation expressions constantes . 5
est une expression constante. new Test()
n'est pas. Par conséquent a
est initialisé avant t
même si les deux sont final statique.
les variables statiques sont initialisées lorsque la classe est chargée par class loader. Ainsi, lorsque la première ligne " static Test t=new Test (); "est exécutée, la valeur de int" a " n'est pas encore initialisée, donc elle s'affiche comme 0. Mais dans les 3 autres cas (c'est-à-dire suppression statique, ajout final ou sans aucun modificateur), ce qui se passe est initialisé au moment de la création D'objet de la classe Test, ce qui se passe dans la première ligne, de sorte qu'elle affiche la valeur "5".
Java Language specification est la meilleure source pour comprendre tout sur l'ordre d'initialisation. Selon votre scénario ,le champ static final
est initialisé avant que toute variable de niveau de classe ne soit initialisée. Lorsque vous retirez la finale, l'initialisation a été reporté. Il convient également de noter si vous changez
static Test t=new Test();
static int a=5;
à
static int a=5;
static Test t=new Test();
il imprimera aussi
a = 5
a = 5
en raison de l'ordre d'initialisation.
static final a=5
il est final
ainsi il initialise d'abord, avant d'autres membres statiques ou des méthodes.
dans le premier scénario main()
la méthode est exécutée en premier et elle initialise a
à sa valeur par défaut 0
.