These are the steps taken when you run your program:
- Before
main
can be run, the Test
class must be initialized by running static initializers in order of appearance.
- To initialize the
me
field, start executing new Test()
.
- Print the value of
I
. Since the field type is Integer
, what seems like a compile-time constant 4
becomes a computed value (Integer.valueOf(4)
). The initializer of this field has not yet run, printing the initial value null
.
- Print the value of
S
. Since it is initialized with a compile-time constant, this value is baked into the referencing site, printing abc
.
new Test()
completes, now the initializer for I
executes.
Lesson: if you rely on eagerly initialized static singletons, place the singleton declaration as the last static field declaration, or resort to a static initializer block that occurs after all other static declarations. That will make the class appear fully initialized to the singleton's construction code.