Risposta breve
Quando l'inizializzazione della classe inizia, k
avrà valore iniziale di 0.
Il blocco statico (dato che precede l'assegnazione nella dichiarazione) viene quindi eseguita, e k
sarà assegnato 2.
Quindi l'inizializzatore nella dichiarazione viene eseguito e k
verrà assegnato 1.
lunga spiegazione
lasciarci usare this example, dal momento che il vostro esempio è un po 'semplice:
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);
}
}
Secondo Java Language Specification, da section 4.12.5:
Ogni variabile in un programma di deve avere un valore prima che venga utilizzato il suo valore:
- Ogni variabile di classe, variabile esempio, o un componente di matrice viene inizializzato con il valore predefinito quando viene creato
(I seguenti righe dalla specifica specificare il valore di default per tutti i tipi, fondamentalmente qualche forma di 0, come 0
, 0.0d
, null
, false
, ecc)
Così prima classe viene inizializzato (a causa di uno dei these reasons), le variabili terrà un valore iniziale.
Secondo il detailed initialization procedure (solo i passi interessanti sono citati qui, e sottolineatura mia):
6. [...] Poi, inizializzare le final
variabili di classe e campi di interfacce i cui valori sono compile-timeespressioni costanti (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
[...]
9. successiva, eseguire sia le inizializzatori classe variabili e inizializzatori statici della classe oi inizializzatori campo dell'interfaccia, in ordine testuale, come se fossero un unico blocco .
Guardiamo al punto 6, con le variabili 4 final
di classe: stat1
, str2
, second
, lazy
.
Da 10
è un'espressione costante, e quindi è "sdfff"
, e causa l'ordine di esecuzione, non è possibile osservare il valore iniziale per str2
e stat1
. Per fare un'osservazione, il primo che puoi fare è al punto 9.
Il caso di second
dimostra che quando il lato destro non è un'espressione costante in fase di compilazione, quindi il suo valore iniziale è visibile.
Il caso di lazy
è diverso, poiché l'assegnazione viene eseguita in blocco statico e quindi avviene nel passaggio 9, quindi è possibile osservare il suo valore iniziale. (Bene, il compilatore controlla attentamente che lazy
sia assegnato esattamente una volta).
Dopo l'inizializzazione delle variabili di classe finali con fase di compilazione espressione costante viene l'esecuzione dei blocchi statici e il resto degli inizializzatori.
Come si può vedere dall'esempio, i blocchi statici e inizializzazione avviene secondo ordine testuale - dimostrata con l'uso di str
variabile - viene prima stampato come null
, quindi something
, quindi crap
.
Per prima cosa, a k verrà assegnato il valore predefinito, quindi dall'alto verrà eseguito il codice statico e verranno assegnati 2, quindi verrà assegnato 1. Quindi viene chiamata la funzione principale e stampata k. 'static int k = 1' è effettivamente' static int k; 'dichiarazione, quindi' static {k = 1; } ' – nhahtdh
@KennyTM Sì, se l'avessi eseguito nel modo in cui in quel post si incolla, vorrei sapere che cosa sta succedendo. – Hoto
@nhahtdh Sarà assegnato il valore predefinito k? Allora perché questo codice non comiple: public class Test { \t \t statica {System.out.println (k); k = 2;} \t static int k; \t \t void main (String [] args) {public static \t \t System.out.println (k); \t} } – Hoto