我正在尝试Java中的初始化顺序,我遇到了一些令人困惑的事情:
static {
System.out.println("Static 1, staticField can't be accessed (compile error)");
staticField = "value"; // NO COMPILE ERROR!
//System.out.println(staticField); // compile error
}
public static String staticField;
static {
System.out.println("Static 2, staticField=" + staticField); // prints "value"
}
如您所见,我们无法引用尚未声明的字段,因此第一个静态块中System.out.println(staticField);
上的编译错误:
在定义字段之前无法引用字段。
但是,可以分配这样的字段,我们可以从第二个静态块中的值判断。
为什么会这样?
答案 0 :(得分:4)
行为列在JLS §8.3.2.3 - Restrictions on the use of Fields during Initialization:
中成员的声明需要以文本形式出现 仅当成员是实例(分别是静态)字段时才使用 类或接口C以及以下所有条件:
用法发生在实例(分别为静态)变量中 C的初始化程序或实例(分别是静态)初始化程序 C。
用法不在作业的左侧。
用法是通过一个简单的名称。
C是封闭用法的最里面的类或接口。
如果上述四个要求中的任何一个是,则是编译时错误 不满足。
基本上,当您在表达式左侧的简单名称上访问static
字段时,根据第二条规则,不应在其之前完成声明。但是,在赋值的右侧使用它,或者尝试在表达式中使用它的值,那么您需要事先声明它,否则它是编译器错误。
换句话说,您可以为这些字段分配任何值,但不能在简单名称上使用它们的值,这是您在print语句中尝试执行的操作。
当然,如果您使用限定名称使用该字段,那么它将起作用。因此,以下代码将编译:
static {
System.out.println("Static 1, staticField can't be accessed (compile error)");
staticField = "value"; // NO COMPILE ERROR!
System.out.println(Main.staticField); // compiles fine now
}