为什么静态init块中的赋值编译没有错误?

时间:2014-03-14 15:38:42

标签: 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 String staticField;

static {
    System.out.println("Static 2, staticField=" + staticField); // prints "value"
}

如您所见,我们无法引用尚未声明的字段,因此第一个静态块中System.out.println(staticField);上的编译错误:

  

在定义字段之前无法引用字段。

但是,可以分配这样的字段,我们可以从第二个静态块中的值判断。

为什么会这样?

1 个答案:

答案 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
}