Previously, it seemed subconsciously that static fields are initialized in the order of their definition — the IL-translator simply takes a block with statics as input and generates the variable initialization algorithm in the intermediate assembly language in the order of their appearance in the input block.

But one situation made me think about how initialization of static fields actually takes place at a lower level:

class Base{ public static final class A { public final static String A = "A"; } public static final class B { public final static String B = AA; } } ... System.out.println(Base.BB); // "A" 

Further:

 class Base{ public static final class A { public final static String A = BB; } public static final class B { public final static String B = "B"; } } ... System.out.println(Base.AA); // "B" 

And the last option:

 class Base{ public static final class A { public final static String A = BB; } public static final class B { public final static String B = AA; } } ... System.out.println(Base.BB); // null System.out.println(Base.AA); // null 

Actually, based on this behavior, it seems obvious the presence of some specific optimization module, which analyzes what is initialized in what order and how to solve situations like the third one.

Is it so? And if so, what kind of optimizer is this, and does it go by default when compiling Java code without additional compilation parameters?

  • 2
    Judging by jls-12.4.2 if during class initialization it is detected that the class is already initialized in the same process, the initialization ends successfully. Therefore, the code does not fall into infinite recursion, but B sees the uninitialized final field. - zRrr

1 answer 1

It seems that the order of loading classes is not disturbed ...

Just in the second and third case in the process of loading A need to load B

In the second case, after loading В , loading А ends.

And in the third case, loading А begins to load В , requiring А ; В sees that А still is not present and puts null for В.В After which А ends and it is logical for А.А to be equal to В.В , i.e. null