Statische Variablen-Initialisierungssequenz
1. Einfache Regeln
Sehen Sie sich zunächst den gebräuchlichsten JAVA-Code an:
public class Test { public static Test1 t = new Test1(); public static int a = 0; public static int b; public static void main(String[] arg) { System.out.println(Test.a); System.out.println(Test.b); } } class Test1 { public Test1() { Test.a++; Test.b++; } }
Raten Sie mal, was die Konsolenausgabe ist
OK, vielleicht haben Sie das Ergebnis unten erraten, dann sind Sie mit Java noch vertraut.
0 1
Wenn Sie nicht verstehen, warum das obige Ergebnis ausgegeben wird, dann lassen Sie es mich Ihnen sagen.
Die Initialisierung statischer Java-Variablen folgt den folgenden Regeln:
Statische Variablen werden in der Reihenfolge der Deklaration deklariert und auf den Standardwert des Typs gesetzt. aber nicht den initialisierten Wert zuweisen.
Nachdem die Deklaration abgeschlossen ist, legen Sie die initialisierten Werte in der Reihenfolge der Deklaration fest. Wenn kein initialisierter Wert vorhanden ist, überspringen Sie ihn.
Nachdem Sie dies gelesen haben, werden Sie verstehen, dass sich der Wert von Test.a dreimal geändert hat.
Bei der Deklaration auf 0 gesetzt>>Test1::In Test1 auf 1 gesetzt>>Test.a wird auf 0 initialisiert
2. Komplexe Regeln
Ich verstehe Bitte schauen Sie sich dazu den folgenden Code noch einmal an.
public class A { public static int b = B.a; public static A plus =new A("A"); public static final int finalInt = (int)(Math.random()*100); public static B p = new B("A"); public static final String finalStr = "finalStr"; public static final Integer finalInteger = new Integer(10); public static int a = 1; public static B c = null; public A(String from) { System.out.println("----------- begin A::A ----------------"); System.out.println("A::A, from="+from); System.out.println("A::A, A.b="+A.b); System.out.println("A::A, A.finalInt="+A.finalInt); System.out.println("A::A, B.a="+B.a); System.out.println("A::A, B.plus="+B.plus); System.out.println("----------- end A::A ----------------"); } public static void main(String[] arg) { System.out.println("main, A.b="+A.b); System.out.println("main, B.t="+B.t); System.out.println("main, C.a="+C.a); } } class B { public static int t = A.a; public static A plus = new A("B"); public static int a = 1; public B(String from) { System.out.println("----------- begin B::B ----------------"); System.out.println("B::B, from="+from); System.out.println("B::B, B.a="+B.a); System.out.println("B::B, A.a="+A.a); System.out.println("B::B, A.p="+A.p); System.out.println("B::B, A.plus="+A.plus); System.out.println("B::B, A.finalInt="+A.finalInt); System.out.println("B::B, A.finalInteger="+A.finalInteger); System.out.println("B::B, A.finalStr="+A.finalStr); System.out.println("----------- end B::B ----------------"); } } class C { public static final A a = new A("C"); }
Können Sie das Ausgabeergebnis noch erraten? Ich habe es beim Testen geschrieben, also habe ich es nicht erraten.
Das Konsolenausgabeergebnis ist:
----------- begin A::A ---------------- A::A, from=B A::A, A.b=0 A::A, A.finalInt=0 A::A, B.a=0 A::A, B.plus=null ----------- end A::A ---------------- ----------- begin A::A ---------------- A::A, from=A A::A, A.b=1 A::A, A.finalInt=0 A::A, B.a=1 A::A, B.plus=A@a90653 ----------- end A::A ---------------- ----------- begin B::B ---------------- B::B, from=A B::B, B.a=1 B::B, A.a=0 B::B, A.p=null B::B, A.plus=A@1fb8ee3 B::B, A.finalInt=61 B::B, A.finalInteger=null B::B, A.finalStr=finalStr ----------- end B::B ---------------- main, A.b=1 main, B.t=0 ----------- begin A::A ---------------- A::A, from=C A::A, A.b=1 A::A, A.finalInt=61 A::A, B.a=1 A::A, B.plus=A@a90653 ----------- end A::A ---------------- main, C.a=A@61de33
Du hast dieses Ergebnis nicht erraten, haha.
Um das Ergebnis der Programmausführung Satz für Satz zu erklären, nimmt es immer noch viel Platz in Anspruch. Hier werde ich direkt die Regeln aufschreiben, denen Java Static folgt Variableninitialisierungsregeln.
Die Regeln im ersten Absatz sind weiterhin gültig, nur nicht stichhaltig.
Nur wenn eine Klasse aktiv angefordert wird, wird diese Klasse initialisiert und enthält nur statische Variablen, Funktionen und andere statische Dinge.
Wenn Sie eine Beziehung erben, initialisieren Sie zuerst die übergeordnete Klasse Initialisieren Sie dann die Unterklasse.
Statische Variablen werden in der Reihenfolge der Deklaration deklariert und auf den Standardwert des Typs gesetzt, ihnen wird jedoch nicht der initialisierte Wert zugewiesen.
Nach der Deklaration Wenn der Wert abgeschlossen ist, wird er in der Reihenfolge der Deklaration festgelegt. Wenn kein initialisierter Wert vorhanden ist, unterbrechen Sie die Initialisierung von A.b und setzen Sie ihn auf B, springen Sie zu Schritt 3 und führen Sie ihn aus.
Wenn Sie B.plus = neues A initialisieren, unterbrechen Sie die Initialisierung von B.plus, instanziieren Sie A und weisen Sie es B.plus zu.
Wann Der Wert von B.a muss im Konstruktor von A abgerufen werden. B.a wird ebenfalls initialisiert und im angehaltenen Initialisierungszustand direkt der aktuelle Wert von B.a übernommen, ohne auf die Initialisierung von B.a zu warten
endgültige, statische Konstanten Befolgen Sie tatsächlich die Initialisierung gewöhnlicher statischer Variablen, aber zur Kompilierungszeit ändert der Compiler die unveränderlichen Konstantenwerte, die Sie verwenden können, um Java-Dekompilierungstools anzuzeigen
Initialisierung statischer Daten
plus statisch qualifizierte Felder sind sogenannte Klassenfelder, was bedeutet, dass der Besitz dieses Feldes kein Objekt, sondern eine Klasse ist. Unabhängig davon, wie viele Objekte erstellt werden, gibt es nur eine Kopie der statischen Daten.
In einer Klasse werden immer zuerst statische Felder und dann allgemeine Felder initialisiert. Dann initialisieren Sie den Konstruktor. Wenn jedoch kein Objekt dieser Klasse erstellt wird, wird das Objekt nicht initialisiert und nur einmal ausgeführt.
Wie im folgenden Code gezeigt, initialisieren Sie in der StaticInitialization-Klasse zuerst die statische Tabelle table = new Table(); und initialisieren Sie dann das Table-Objekt, andernfalls wird es nicht initialisiert.
Ausgabe:class Bowl { Bowl(int marker) { print("Bowl(" + marker + ")"); } void f1(int marker) { print("f1(" + marker + ")"); } } class Table { static Bowl bowl1 = new Bowl(1); Table() { print("Table()"); bowl2.f1(1); } void f2(int marker) { print("f2(" + marker + ")"); } static Bowl bowl2 = new Bowl(2); } class Cupboard { Bowl bowl3 = new Bowl(3); static Bowl bowl4 = new Bowl(4); Cupboard() { print("Cupboard()"); bowl4.f1(2); } void f3(int marker) { print("f3(" + marker + ")"); } static Bowl bowl5 = new Bowl(5); } public class StaticInitialization { public static void main(String[] args) { print("Creating new Cupboard() in main"); new Cupboard(); print("Creating new Cupboard() in main"); new Cupboard(); table.f2(1); cupboard.f3(1); } static Table table = new Table(); static Cupboard cupboard = new Cupboard(); }
Bowl(1) Bowl(2) Table() f1(1) Bowl(4) Bowl(5) Bowl(3) Cupboard() f1(2) Creating new Cupboard() in main Bowl(3) Cupboard() f1(2) Creating new Cupboard() in main Bowl(3) Cupboard() f1(2) f2(1) f3(1)
class Cup { Cup(int marker) { print("Cup(" + marker + ")"); } void f(int marker) { print("f(" + marker + ")"); } } class Cups { static Cup cup1; static Cup cup2; static { cup1 = new Cup(1); cup2 = new Cup(2); } Cups() { print("Cups()"); } } public class ExplicitStatic { public static void main(String[] args) { print("Inside main()"); Cups.cup1.f(99); // (1) } // static Cups cups1 = new Cups(); // (2) // static Cups cups2 = new Cups(); // (2) }
Inside main() Cup(1) Cup(2) f(99)
Nicht statische Instanzinitialisierung
class Mug { Mug(int marker) { print("Mug(" + marker + ")"); } void f(int marker) { print("f(" + marker + ")"); } } public class Mugs { Mug mug1; Mug mug2; { mug1 = new Mug(1); mug2 = new Mug(2); print("mug1 & mug2 initialized"); } Mugs() { print("Mugs()"); } Mugs(int i) { print("Mugs(int)"); } public static void main(String[] args) { print("Inside main()"); new Mugs(); print("new Mugs() completed"); new Mugs(1); print("new Mugs(1) completed"); } }
Inside main() Mug(1) Mug(2) mug1 & mug2 initialized Mugs() new Mugs() completed Mug(1) Mug(2) mug1 & mug2 initialized Mugs(int) new Mugs(1) completed