Kurze Antwort
Wenn die Initialisierung der Klasse beginnt, wird k
hat Anfangswert von 0.
Der statische Block (da es die Zuordnung in der Erklärung vorangestellt) wird dann ausgeführt, und k
wird zugewiesen 2.
Dann wird der Initialisierer in der Deklaration ausgeführt und k
wird 1 zugewiesen.
Lange Erklärung
uns this example Lassen Sie verwenden, da Ihr Beispiel ein bisschen einfach:
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);
}
}
Nach Java Language Specification von section 4.12.5:
Jede Variable in einem Programm muss einen Wert haben, bevor der Wert verwendet wird:
- Jede Klassenvariable, Instanzvariablen oder Arraykomponente wird mit einem Standardwert initialisiert, wenn es
erstellt wird
(die folgenden Zeilen aus der Beschreibung um den Standardwert für alle Typen spezifizieren, im Grunde irgendeine Form von 0, wie 0
, 0.0d
, null
, false
, etc.)
Also, bevor die Klasse (aufgrund eines von these reasons) initialisiert wird, werden die Variablen einen Anfangswert halten.
Nach dem detailed initialization procedure (nur die interessanten Schritte werden hier zitiert, und Hervorhebung von mir):
6. [...] Dann initialisieren die final
Klassenvariablen und Bereichen Schnittstellen, deren Werte Kompilierung-konstante Ausdrücke (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
[...]
9. Als nächstes ausführen entweder die Klassen Variableninitialisierungen und statische Initialisierungen der Klasse, oder das Feld initializers die Schnittstelle in Text Ordnung, als ob sie ein einzelner Block waren .
wir in Schritt 6 mit dem 4 final
Klassenvariablen Werfen sie einen Blick: stat1
, str2
, second
, lazy
.
Da 10
ist konstanter Ausdruck, und so ist "sdfff"
, und aufgrund der Reihenfolge der Ausführung, ist es nicht möglich, für str2
und stat1
den Anfangswert zu beobachten. Um eine Beobachtung zu machen, ist der früheste Schritt in Schritt 9.
Der Fall second
zeigt, dass, wenn die rechte Seite kein kompilierbarer Konstantenausdruck ist, der Anfangswert sichtbar ist.
Der Fall von lazy
ist anders, da die Zuweisung im statischen Block erfolgt und daher in Schritt 9 geschieht - so ist es möglich, seinen Anfangswert zu beobachten. (Nun, der Compiler überprüft sorgfältig, dass lazy
genau einmal zugewiesen ist).
Nach der Initialisierung der endgültigen Klassenvariablen mit Kompilierung-Konstante Ausdruck kommt die Ausführung von statischen Blöcken und den Rest des initializers.
Wie man aus dem Beispiel sind die statischen Blöcke und die Initialisierung geschieht gemäß textliche Reihenfolge sehen - gezeigt mit der Verwendung von str
variable - es zunächst als null
ausgedruckt wird, dann something
, dann crap
.
Zuerst wird k der Standardwert zugewiesen, dann wird von oben der statische Code ausgeführt und 2 zugewiesen, dann wird 1 zugewiesen. Dann wird die Hauptfunktion aufgerufen und k ausgedruckt. 'static int k = 1' ist effektiv' static int k; 'deklaration, dann' static {k = 1; } ' – nhahtdh
@KennyTM Ja, wenn ich es so gelaufen wäre wie in diesem Post Du einfügen, würde ich wissen, was los ist. – Hoto
@nhahtdh Wird k Standardwert zugewiesen? Dann warum dieser Code nicht comiple: public class Test { \t \t static {System.out.println (k); k = 2;} \t static int k; \t \t public static void main (String [] args) { \t \t System.out.printin (k); \t} } – Hoto