I tried to understand the behavior of initialization order when static fields are initialized with a reference to the same enclosing class object.
public class Test {
static final Test t=new Test();
static int a=5;
Test(){
System.out.println("a="+a);
}
public static void main(String[] args) {
new Test();
}
}
Output of above piece of code is:
a=0
a=5
If I modify variable a
to anything else other than plain static
:
static final a=5;
a=5;
final a=5;
The output is:
a=5
a=5
Why is this behavior?
Note that the output is a=5 & a=5
even when both t & a
are declared as static final
in which case t
precedes the declaration of a
static final members are initialized before other static members.
non final static members are initialized in order of appearance
Therefore, in your first case :
The constructor is first called before
a
is initialized, soa=0
is displayed.In the second case,
static final a
is initialized beforet
, soa=5
is displayed when the first instance ofTest
is created. Whena
is not static, it is initialized prior to the execution of the constructor, so againa=5
is displayed.Regarding the edit in your question.
Looking at section 12.4.2 of the JLS :
You see that final class variables (i.e. static final) are initialized before the rest of the static variables only if their values are compile time constant expressions.
5
is a constant expression.new Test()
is not. Thereforea
is initialized beforet
even if both are static final.static final a=5
It isfinal
so it initialize first, before other static members or methods.In first scenario
main()
method get executed first and it initializea
to its default value0
.Static variables are initialized when the class gets loaded by class loader. So when first line “static Test t=new Test();” gets executed, the value of int “a” is not yet initialized, hence it is showing as 0. But other 3 cases (i.e. removing static, adding final or without any modifier) what happens a gets initialized at the time of Object creation of Test class, which is happening in the first line so it is showing the value “5”.
Java Language specification is best source to understand all about initialization order. According to that in your scenario,
static final
field gets initialized before any class level variable gets initialized. When you remove the final, initialization was deferred. It should also be noted if you changeto
it will also print
because of initialization order.