This is the wrong 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() ; } }
Why do I still get an error after initializing a in the static code block?
The reason involves Java's restrictions on member variables during the initialization process:
If member variable a meets the following four points, the member variable must be declared before use
Set C as a class or interface that directly contains the member variable
If a appears in C or a static member/non-static member Initialization or C static or non-static code block
If a is not an lvalue of an assignment inequality
Accessed by simple name
In the code I wrote, a.printA() ; appears in the static code block of CC, and is directly accessed through a simple name (that is, using a directly), and It is not an lvalue of the assignment inequality, so the error "illegal forward reference" will be reported
This is the original code in the Java language specification (the Chinese in it is my own annotation):
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; }
Example of illegal forward reference:
So why Is a code like i="1234"; okay?
This is because Java has "concessions" for some of these situations. One of them is "Variables referenced by simple names can appear in lvalue positions, but not in rvalue positions." position", so the previous code works, but System.out.println(i); does not, because this is an rvalue reference.
The purpose is to avoid loop initialization and other abnormal initialization behaviors.
What is a circular reference? Take a look at the following example:
privateinti=j; privateintj=i;
If there is no mandatory check mentioned above, then these two lines of code will be compiled, but it is easy to It can be seen that i and j are not actually assigned values because both variables are uninitialized (Java stipulates that all variables must be initialized before use)
The above is the detailed content of How to solve the problem of illegal forward reference in java. For more information, please follow other related articles on the PHP Chinese website!