Your concern is that the enums would be somehow accessed without static init of its outer class but this is impossible. The enum accesses an outer class member:
private Message() {
text = MESSAGES.getProperty(name());
} // ^ static field of Log
Accessing MESSAGES
will cause Log
to be loaded and initialized if it's not already.
"I don't see how the static initializer could ever not run first (since references to Message have to go through Log, e.g. Log.Message.IOEXCEPTION)"
Accessing the nested class through the outer class name doesn't cause the outer class to be initialized.
For the record, here is the list of what causes a class to be initialized (JLS 12.4.1):
T is a class and an instance of T is created.
T is a class and a static method declared by T is invoked.
A static field declared by T is assigned.
A static field declared by T is used and the field is not a constant variable (§4.12.4).
T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.
(Emboldened is the one causing Log
to be initialized.)
And although MESSAGES
is static and final, it's not a constant variable in the eyes of the JLS. Constant variables are defined in final Variables as the following:
A variable of primitive type or type String, that is final and initialized with a compile-time constant expression...