Heim  >  Artikel  >  Java  >  Vollständige Analyse der Initialisierung statischer Variablen in Java

Vollständige Analyse der Initialisierung statischer Variablen in Java

高洛峰
高洛峰Original
2017-01-24 17:03:202217Durchsuche

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();
}

Angezeigte statische Initialisierung (d. h. statischer Block)
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)
Das Einschließen mehrerer Initialisierungsanweisungen in eine statische geschweifte Klammer wird tatsächlich als statischer Block bezeichnet , mehrere Statiken werden zusammen geschrieben, und das Wesentliche ist dasselbe. Es wird nur ausgeführt, wenn das Objekt zum ersten Mal erstellt wird oder zum ersten Mal auf ein Feld der Klasse zugegriffen wird, und zwar nur einmal.


Ausgabe:
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

Es gibt nichts zu besprechen, es ist nur eine normale Initialisierung. der Reihe nach ausgeführt werden, kann mehrmals ausgeführt werden.


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");
 }
}
Weitere Artikel zur vollständigen Analyse der Initialisierung statischer Variablen in Java finden Sie auf der chinesischen PHP-Website!
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
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn