Creating an object in a static way
Solution 1:
- Class initialization starts. Initially,
foo
is null andsFlag
is false - The first static variable initializer (
foo
) runs:- A new instance of
Foo
is created - The instance variable initializer for
flag
executes - currentlysFlag
is false, so the value offlag
is false
- A new instance of
- The second static variable initializer (
sFlag
) executes, setting the value to true - Class initialization completes
-
main
runs, printing outfoo.flag
, which is false
Note that if sFlag
were declared to be final
it would be treated as a compile-time constant, at which point all references to it would basically be inlined to true
, so foo.flag
would be true too.
Solution 2:
foo
is instantiated during the static initialization of the class, and before sFlag was initialized, and the default value of a boolean is false.
- The class is loaded
-
Foo is initialized to the instance
2.a The instance member flag is initialized to the value of sFlag (
false
by default) - sFlag is initialized to true
Please refer to JLS §12.4 for more details.
Solution 3:
When class is loaded, sFlag
and foo
fields are initialized but foo
is initialized first!
fields flag
and sFlag
are boolean and can't be null so by default there're false and sFlag
is still false when foo
is being initialized. flag = sFlag
after this flag
is false.That's it
Solution 4:
The general order of initialization operations is (after the class is loaded and before first use):
- Static (class) code blocks in order it appears in the code,
- Object code blocks in order it appears in the code (initialization blocks and assignments).
- Constructors
Certainly I don't refer constructors and functions body as a code block above .
I don't know how about final static
fields. It looks like they follow the rules of static
fields and they cannot be referenced before declaration despite previous comments that they are initialized at compilation step. If they are referenced before there is a compilation error:
Example.java:8: illegal forward reference
System.err.println("1st static block j=" + j);
Maybe final static
fields can be initialized and compiled into the class file but this is not a general rule and they still cannot be referenced before declaration.
Example code to check initialization order:
class Example {
final static int j = 5;
{
System.err.println("1st initializer j=" + j);
}
static {
System.err.println("1st static block j=" + j);
}
static {
System.err.println("2nd static block j=" + j);
}
final static java.math.BigInteger i = new java.math.BigInteger("1") {
{
System.err.println("final static anonymous class initializer");
}
};
Example() {
System.err.println("Constructor");
}
static {
System.err.println("3nd static block j=" + j);
}
{
System.err.println("2nd initializer");
}
public static void main(String[] args) {
System.err.println("The main beginning.");
Example ex = new Example();
System.err.println("The main end.");
}
}
The above code snipset prints:
1st static block j=5
2nd static block j=5
final static anonymous class initializer
3nd static block j=5
The main beginning.
1st initializer j=5
2nd initializer
Constructor
The main end.