JLS中是否有关于执行静态初始化块的顺序的保证?

Rom*_*man 2 java static-initialization jls

我想知道使用如下构造是否可靠:

private static final Map<String, String> engMessages;
private static final Map<String, String> rusMessages;

static {
    engMessages = new HashMap<String, String> () {{
        put ("msgname", "value");
    }};
    rusMessages = new HashMap<String, String> () {{
        put ("msgname", "????????");
    }};
}

private static Map<String, String> msgSource;

static {
    msgSource = engMessages;
}

public static String msg (String msgName) {
    return msgSource.get (msgName);
}
Run Code Online (Sandbox Code Playgroud)

有可能我会得到NullPointerException因为msgSource初始化块之前会执行初始化块engMessages吗?

(关于为什么我不在msgSource初始化结束时进行初始化.块:只是味道问题;如果描述的结构不可靠,我会这样做)

Jon*_*eet 7

是的,保证静态初始化程序块以文本顺序执行.

从JLS 第12.4.1节:

目的是类或接口类型具有一组初始化器,使其处于一致状态,并且该状态是其他类观察到的第一个状态.静态初始值设定项和类变量初始值设定项以文本顺序执行,并且可能不引用在声明在使用后以文本方式出现的类中声明的类变量,即使这些类变量在范围内(第8.3.3节).此限制旨在在编译时检测大多数循环或其他格式错误的初始化.

12.4.2开始:

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

就个人而言,我将所有变量声明放在开头,然后是一个静态初始化块.我认为这更容易遵循.