public class Test {
static {
i = 100;
// System.out.println("================================"+i);
}
public static int i=10;
public static void main(String[] args) {
System.out.println("此时 i 的输出为" + i);
}
}
上面的注释这行代码为什么会报错:非法向前引用?
这个时候我debug都可以看到i的值是100.为什么不能打印出来呢?
原因就涉及了java对于初始化过程中对成员变量的限制:
成员变量a如果满足如下的4点,就必须在使用前必须对该成员变量进行声明
设定Test为直接包含该成员变量的类或者接口
如果i出现在在Test的或静态成员/非静态成员初始化 或者 Test的静态或非静态代码块中
如果i不是 一个赋值不等式的左值
通过简单名称来访问
在我自己写的代码中,a.printA() ;出现的位置是Test的静态代码块中,通过简单名称直接访问(也就是直接使用a), 并且不是赋值不等式的左值,所以会报错“非法的前向引用”
这个是java语言规范中的原文代码(其中的中文是我自己的标注):
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;
}