These are the steps taken when you run your program:
- Before
maincan be run, theTestclass must be initialized by running static initializers in order of appearance. - To initialize the
mefield, start executingnew Test(). - Print the value of
I. Since the field type isInteger, what seems like a compile-time constant4becomes a computed value (Integer.valueOf(4)). The initializer of this field has not yet run, printing the initial valuenull. - Print the value of
S. Since it is initialized with a compile-time constant, this value is baked into the referencing site, printingabc. new Test()completes, now the initializer forIexecutes.
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.