Java 为什么静态init块中的赋值编译时没有错误?
我在用Java进行初始化顺序的实验时,遇到了一些非常令人困惑的问题:Java 为什么静态init块中的赋值编译时没有错误?,java,initialization,Java,Initialization,我在用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 St
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)上出现编译错误第一个静态块中的代码>:
在定义字段之前,无法引用该字段
但是,可以指定这样一个字段,我们可以从第二个静态块中的值看出这一点
为什么会这样?行为列在:
成员的声明需要以文本形式出现,然后才能被删除
仅当成员是的实例(分别为静态)字段时使用
类或接口C和以下所有条件均成立:
- 该用法发生在实例(分别为静态)变量中
C的初始值设定项或实例中的(分别为静态)初始值设定项
C
- 用法不在作业的左侧
- 用法是通过一个简单的名称
- C是包含用法的最内层类或接口
如果以上四个要求中的任何一个被忽略,则这是编译时错误
没有遇见
基本上,当您访问表达式左侧简单名称上的静态
字段时,根据第二条规则,不应在其前面进行声明。但是,如果在赋值的右侧使用它,或者试图在表达式中使用它的值,则需要事先声明它,否则这是编译器错误
换句话说,您可以为这些字段分配任何值,但不能在简单名称上使用它们的值,这是您在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
}
我认为编译器在执行静态变量之前读取所有静态变量引用blocks@karim是的,但问题是,如果定义了变量,为什么在声明后不能使用它,但可以初始化?@karim Static fields初始化和Static init块按照Java文档的源代码顺序执行。但是,我没有发现关于声明本身的任何信息(与初始化相反)。无论如何,如果字段声明是以前读过的,那么为什么读访问是不可能的,而写访问是不可能的?关于在引用变量之前声明变量的规则实际上只适用于局部变量。@Hot-Licks那么为什么System.out.println(staticField)上有编译错误代码>?我明白了。但奇怪的是,在类中声明字段时,我们需要一个完全限定的名称。@Joffrey有些东西是我们无法推理的,原因很简单,因为语言就是这样设计的。我不是评论这是否正确的合适人选。乍一看可能有点奇怪,但你会习惯这些规则的。他们太多了。幸运的是,您几乎总能在JLS中找到原因:)是的,没错^^我想有一些原因可以简化编译器。无论如何,谢谢你的回答!