Das ist der falsche Code:
class BB { static int a = 0 ; public BB() { a++ ; System.out.println("执行BB" + a) ; } public void printA() { System.out.println("a= " + a) ; } } public class CC { static { a = new BB() ; a.printA() ; //报错说非法的前向引用 } static BB a = new BB() ; public staic void main(String args[]) { CC c = new CC() ; } }
Warum initialisiere ich a im statischen Codeblock und erhalte trotzdem eine Fehlermeldung?
Der Grund liegt in den Einschränkungen von Java für Mitgliedsvariablen während des Initialisierungsprozesses:
Wenn Mitgliedsvariable a die folgenden 4 Punkte erfüllt, muss sie vor der Verwendung deklariert werden
Setzen Sie C als direkt ein. Die Klasse oder Schnittstelle, die die Mitgliedsvariable enthält
Wenn a in C oder der Initialisierung statischer Member/nicht-statischer Member oder im statischen oder nicht-statischen Codeblock von C erscheint
Wenn a kein L-Wert einer Zuweisungsungleichung ist
Zugriff über einfache Namen
In dem von mir geschriebenen Code erscheint a.printA() ; im statischen Codeblock von CC und wird direkt über einfache Namen (d. h. direkt über a) aufgerufen und ist kein L-Wert der Zuweisungsungleichung. Daher wird ein Fehler „Ungültige Vorwärtsreferenz“ gemeldet
Dies ist der Originalcode in der Java-Sprachspezifikation (das Chinesisch darin ist meine eigene Anmerkung):
class UseBeforeDeclaration { static { x = 100; // ok - assignment , 赋值表达式的左值 int y = x + 1; // error - read before declaration , 赋值表达式的右值 int v = x = 3; // ok - x at left hand side of assignment , 左值 int z = UseBeforeDeclaration.x * 2; // ok - not accessed via simple name , 是通过类.静态变量 的形式访问, 而非直接简单访问 Object o = new Object() { void foo() { x++; } // ok - occurs in a different class , 不是CC的代码块或成员初始化中,而是在一个全新的内部类的函数中 { x++; } // ok - occurs in a different class , 在一个内部类的代码块中, 和上一个类似 }; } { j = 200; // ok - assignment j = j + 1; // error - right hand side reads before declaration , 第二个右值 int k = j = j + 1; // error - illegal forward reference to j , 第三个是右值 int n = j = 300; // ok - j at left hand side of assignment , 左值 int h = j++; // error - read before declaration , 右值, 并参与了自增运算 int l = this.j * 3; // ok - not accessed via simple name 通过this.j进行访问, 非直接简单访问 Object o = new Object() { void foo() { j++; } // ok - occurs in a different class { j = j + 1; } // ok - occurs in a different class }; } int w = x = 3; // ok - x at left hand side of assignment int p = x; // ok - instance initializers may access static fields static int u = (new Object() { int bar() { return x; } }).bar(); // ok - occurs in a different class static int x; int m = j = 4; // ok - j at left hand side of assignment int o = (new Object() { int bar() { return j; } }).bar(); // ok - occurs in a different class int j; }
Beispiel für eine illegale Vorwärtsreferenz :
Warum ist Code wie i="1234" in Ordnung?
Das liegt daran, dass Java für einige dieser Situationen „Konzessionen“ hat. Eine davon ist „Variablen, auf die durch einfache Namen verwiesen wird, können an L-Wert-Positionen erscheinen, aber nicht an R-Wert-Positionen“, also funktioniert der vorherige Code, aber das System. out.println(i); funktioniert nicht, da es sich um eine R-Wert-Referenz handelt.
Der Zweck besteht darin, Schleifeninitialisierung und andere abnormale Initialisierungsverhalten zu vermeiden.
Was ist ein Zirkelverweis? Schauen Sie sich das folgende Beispiel an:
privateinti=j; privateintj=i;
Wenn oben keine obligatorische Prüfung vorhanden ist, werden diese beiden Codezeilen kompiliert, aber es ist leicht zu erkennen, dass i und j vorhanden sind nicht gewesen Echte Zuweisung, da beide Variablen nicht initialisiert sind (Java schreibt vor, dass alle Variablen vor der Verwendung initialisiert werden müssen)
Das obige ist der detaillierte Inhalt vonSo lösen Sie das Problem illegaler Vorwärtsreferenzen in Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!