2012-11-25 17 views
7

Mögliche Duplizieren:
Java static class initialization
in what order are static blocks and static variables in a class executed?Reihenfolge der statischen Variablen Initialisierung, Java

Wenn ich diesen Code ausführen die Antwort 1 ist, dachte ich, es wäre 2. Was ist die Reihenfolge der Initialisierung und der Wert von k in jedem Schritt?

Edit 1: Als Folge zu "k ist auf den Standardwert eingestellt" dann warum kompiliert dieser nächste Code nicht? Es gibt einen Fehler "Kann ein Feld nicht referenzieren, bevor es definiert wurde".

public class Test { 

static {System.out.println(k);} 
static int k=1; 

public static void main(String[] args) { 
    System.out.println(k); 
} 
} 

Edit 2: Denn für mich einige unknow es Grund^funktioniert, wenn anstelle von "k" seine "Test.k".

Danke für alle Antworten. dies genügt: D

+1

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

+0

@KennyTM Ja, wenn ich es so gelaufen wäre wie in diesem Post Du einfügen, würde ich wissen, was los ist. – Hoto

+0

@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

Antwort

7

Sie werden in der Reihenfolge ausgeführt, in der Sie sie schreiben. Wenn der Code:

public class Test { 

    static int k = 1; 
    static {k = 2;} 

    public static void main(String[] args) { 
     System.out.println(k); 
    } 

} 

dann wird das Ausgangssignal 2.

Die Reihenfolge der Initialisierung ist: ..the class variable initializers and static initializers of the class..., in textual order, as though they were a single block.

Und die Werte (für Ihren Code) sind: k = 0 (Standard), es ist dann auf 2 gesetzt ist, dann wird es zurückgesetzt auf 1.

Sie können prüfen, ob es auf 2 tatsächlich eingestellt ist durch den folgenden Code ausführen:

private static class Test { 

    static { 
     System.out.println(Test.k); 
     k = 2; 
     System.out.println(Test.k); 
     } 
    static int k = 1; 

    public static void main(String[] args) { 
     System.out.println(k); 
    } 
} 
+0

Das ist nicht was ich in meiner Frage gemeint habe. Ich wollte die Reihenfolge der Initialisierung und Werte von k in jedem Schritt. – Hoto

+0

Ok, ich habe eine detailliertere Erklärung hinzugefügt. – tibtof

+0

Ja ... aber jetzt gibt es ein bisschen Chaos in Ihrer Antwort xD – Hoto

3

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.

+0

@EJP: Beachten Sie, dass 2 Bedingungen 1) ** letzte ** Klassenvariablen und 2) Initialisierer ist Kompilierzeitkonstante, die in durchgeführt wird Schritt 6. Kein Widerspruch hier. Sie können sogar das Programm auf ideone auschecken. – nhahtdh

Verwandte Themen