在声明之前,如何访问静态变量?
-
02-10-2019 - |
题
public class Main {
static int x = Main.y;
// static int x = y; //Not allowed; y is not defined
static int y = x;
public static void main(String[] args) {
System.out.println(x);//prints 0
}
}
我怎么被允许使用Y槽,但不直接?
y什么时候定义?
解决方案
在本节中描述了有关类变量的前期参考的确切规则 §8.3.2.3 JLS:
8.3.2.3初始化期间使用字段的限制
仅当成员是一个实例时,成员的声明才需要在使用文本之前出现(分别
static
)类或接口C的字段以及以下所有条件所保存:
- 用法发生在一个实例中(分别
static
)C的可变初始化器或在一个实例中(分别static
)C的初始化器。- 用法不在作业的左侧。
- 用法是通过一个简单的名称。
- C是封闭用法的最终类或接口。
如果未满足上述四个要求中的任何一个,则会发生编译时间误差。
这意味着编译时间错误来自测试程序:
class Test { int i = j; // compile-time error: incorrect forward reference int j = 1; }
而以下示例没有错误地编译:
class Test { Test() { k = 2; } int j = 1; int i = j; int k; }
即使构造函数 (§8.8) 对于测试,指的是在三行之后声明的字段k。
这些限制旨在在编译时捕获循环或以其他方式畸形的初始化。因此,两者都:
class Z { static int i = j + 2; static int j = 4; }
和:
class Z { static { i = j + 2; } static int i, j; static { j = 4; } }
导致编译时错误。不以这种方式检查通过方法访问,因此:
class Z { static int peek() { return j; } static int i = peek(); static int j = 1; } class Test { public static void main(String[] args) { System.out.println(Z.i); } }
产生输出:
0
因为i的变量初始化程序使用类方法窥视访问j的变量J的值 (§4.12.5).
其他提示
我认为,通过使用类,编译器会推迟到该变量直到班级完成,因此找到y,但是如果您只是像评论一样定义它,则尚未定义,因此它会失败。
静态变量是按照课堂加载期间按声明的声明顺序定义的。当JVM会加载 Main
班级, x
将定义,然后 y
. 。这就是为什么您不能直接使用 y
初始化时 x
, ,您创建的东西称为 向前参考, ,您是指当前未定义的变量,这对编译器来说是非法的。
使用时 Main.y
, ,我认为以下发生了以下情况:
- 你加载
Main
,x
调用初始化 - 定义时
x
等于Main.y
, ,编译器看到对类的引用,因此它将结束定义x
到成员的当前价值y
班级Main
. 。它将这种情况视为Main
是不同的班级。
请注意,在这种情况下,初始化时 x
, y
目前尚未定义。所以 x
将有一个价值 0
.
您不允许这样做,因为它毫无意义。唯一可能的解释是 y 初始化为零,您已经有两种说法。您不需要这个。
也许编译器创建静态变量的引用,并在堆栈中的类中,创建默认值,然后分配提供的值。
不隶属于 StackOverflow