Réponse courte
Lorsque l'initialisation de la classe commence, k
aura une valeur initiale de 0.
Le bloc statique (puisqu'elle précède l'attribution dans la déclaration) est ensuite exécutée, et k
sera affecté 2.
Ensuite, l'initialiseur dans la déclaration est exécuté et k
est affecté 1.
longue explication
Utilisons this example, puisque votre exemple est un peu simple:
class TestInitOrder {
static {
System.out.println(TestInitOrder.stat1);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
str = "something";
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
private static final int stat1 = 10;
static final String str2 = "sdfff";
static String str = "crap";
private static int stat2 = 19;
static final Second second = new Second();
static final int lazy;
static {
lazy = 20;
}
static {
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
public static void main(String args[]) {
}
}
class Second {
public Second() {
System.out.println(TestInitOrder.second);
}
}
Selon Java Language Specification, de section 4.12.5:
Chaque variable dans un programme doit avoir une valeur avant que sa valeur soit utilisée:
- Chaque variable de classe, variable d'instance, ou d'un composant de tableau est initialisé avec une valeur par défaut lors de sa création
(Les lignes suivantes de la spécification spécifier la valeur par défaut pour tous les types, essentiellement une certaine forme de 0, comme 0
, 0.0d
, null
, false
, etc.)
Alors avant de la classe est initialisé (en raison de l'un des these reasons), les variables tiendra une valeur initiale.
Selon le detailed initialization procedure (seules les étapes intéressantes sont cités ici, et moi qui souligne):
6. [...] Ensuite, initialiser les final
variables de classe et champs d'interfaces dont les valeurs sont à la compilationexpressions constantes (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
[...]
9. Ensuite, exécutez l'une des initialiseurs variables de classe et initialiseurs statiques de la classe, ou les initialiseurs sur le terrain de l'interface, dans l'ordre textuel, comme si elles étaient un seul bloc .
Penchons-nous à l'étape 6, avec les 4 final
variables de classe: stat1
, str2
, second
, lazy
.
Depuis 10
est l'expression constante, et ainsi est "sdfff"
, et en raison de l'ordre d'exécution, il est impossible de observer la valeur initiale pour str2
et stat1
. Pour faire une observation, le plus tôt possible est à l'étape 9.
Le cas de second
montre que lorsque le membre de droite n'est pas une expression de constante de compilation, sa valeur initiale est visible.
Le cas de lazy
est différent, car l'affectation est faite en bloc statique, et se produit donc à l'étape 9 - il est donc possible d'observer sa valeur initiale. (Eh bien, le compilateur vérifie soigneusement que lazy
est affecté exactement une fois).
Après l'initialisation de variables de classe finale avec une expression constante de temps de compilation vient l'exécution des blocs statiques et le reste des initializers.
Comme vous pouvez le voir dans l'exemple, les blocs statiques et l'initialisation se produit selon l'ordre textuel - démontré avec l'utilisation de str
variable - il est d'abord imprimé comme null
, puis something
, puis crap
.
D'abord, la valeur par défaut sera attribuée à k, puis, à partir du haut, le code statique sera exécuté et 2 seront attribués, puis 1 sera attribué. Ensuite, la fonction principale est appelée et imprimée k. 'static int k = 1' est effectivement' static int k; 'declaration, alors' static {k = 1; } ' – nhahtdh
@KennyTM Oui, si j'avais couru le chemin comme dans ce post Vous collez, je saurais ce qui se passe. – Hoto
@nhahtdh Une valeur par défaut sera-t-elle attribuée à k? Alors, pourquoi ce code n'a pas comiple: public class Test { \t \t statique {System.out.println (k); k = 2;} \t int k statique; \t \t public static void main (String [] args) { \t \t System.out.println (k); \t} } – Hoto