我可以在声明之前访问静态块中的静态字段吗?

Sha*_*yaz 1 java static static-block

我对下面的代码感到困惑,我预计它会给出一个错误或答案是10但是它给出了20怎么样?

public class test {
    public static void main(String[] args) {
        System.out.println(x);
    }

    static{
        x=10;
    }

    static int x=20;
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 8

在JLS的第12.4.2节中指定,它提供了类初始化的详细信息:

接下来,按文本顺序执行类的类变量初始值设定项和类的静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样.

变量initializer(x = 20)发生在x = 10程序文本中的静态初始化程序(包含块)之后.因此,初始化结束时的值为20.

如果您交换订单轮以使变量初始化程序首先出现,那么您将看到10.

我强烈建议你尽量避免编写依赖于文本排序的代码.

编辑:变量仍然可以在静态初始化程序中使用,因为它在范围内 - 就像您可以在早于变量声明的方法中使用实例变量一样.但是,第8.3.2.3节对此给出了一些限制:

只有当成员是类或接口C的实例(分别是静态)字段并且满足以下所有条件时,成员的声明才需要以文本方式显示:

  • 用法发生在C的实例(分别是静态)变量初始化器或C的实例(分别是静态)初始化器中.

  • 用法不在作业的左侧.

  • 用法是通过一个简单的名称.

  • C是封闭用法的最内层类或接口.

如果不满足上述四个要求中的任何一个,则为编译时错误.

因此,如果您将静态初始化程序更改为:

static {
    System.out.println(x);
}
Run Code Online (Sandbox Code Playgroud)

然后你会收到一个错误.

但是,您现有的静态初始化程序以x符合所有限制的方式使用.