我遇到了一件有趣的事情:
static {
System.out.println(test); // error cannot reference a field before it is defined
System.out.println(cheat()); // OK!
}
private static boolean cheat() {
return test;
}
private static boolean test = true;
public static void main(String args[]) {}
第一种方法是错误的,你的编译器和IDE都会告诉你这是错误的。在第二种情况下,作弊是可以的,但它实际上默认字段test
为false
。使用Sun JDK 6。
答案 0 :(得分:11)
这是在JLS 8.3.2.3中定义的。特别是:
成员的声明需要在使用之前以文本方式显示[...]如果用法发生在C的静态初始值设定项中。
当你致电cheat()
时,你会绕过那个规则。这实际上是该部分the list of the examples中的第五个例子。
请注意,cheat()
将在静态初始化程序块中返回false,因为test
尚未初始化。
答案 1 :(得分:3)
因为类加载按此顺序进行:
test
) - 尚未初始化static
初始值设定项(用于变量)和static
块 - 按顺序执行因此,当您到达static
块时,您已准备好方法定义,但没有准备好变量。使用cheat()
,您实际上正在读取未初始化的值。
答案 2 :(得分:1)
这是类加载发生的通用步骤。
准备好之后,你的测试将是假的。然后在将静态变量赋值为true之前,你的静态块将会执行。这就是你得失的原因。
尝试使你的静态变量最终。在这种情况下,你将成为现实。这是因为你的编译器本身将在字节码中嵌入值(因为字段是最终的)作为优化的一部分