Are there any guarantees in JLS about order of execution static initialization blocks?
I wonder if it's reliable to use a construction like:
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);
}
Is there a possibility that I'll get NullPointerException
because msgSource
initialization block will be executed before the block which initializes engMessages
?
(about why don't I do msgSource
initialization at the end of upper init. block: just the matter of taste; I'll do so if the described construction is unreliable)
Yes, static initializer blocks are guaranteed to execute in textual order.
From the JLS, section 12.4.1:
The intent is that a class or interface type has a set of initializers that put it in a consistent state, and that this state is the first state that is observed by other classes. The static initializers and class variable initializers are executed in textual order, and may not refer to class variables declared in the class whose declarations appear textually after the use, even though these class variables are in scope (§8.3.3). This restriction is designed to detect, at compile time, most circular or otherwise malformed initializations.
And from 12.4.2:
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
Personally though, I'd put all the variable declarations at the start, and then a single static initializer block. I consider that to be a lot easier to follow.