Short answer
When the initialization of the class starts, k
will have initial value of 0.
The static block (since it precedes the assignment in the declaration) is then executed, and k
will be assigned 2.
Then the initializer in the declaration is executed, and k
will be assigned 1.
Long explanation
Let us use this example, since your example is a bit simple:
class TestInitOrder {
static {
System.out.println(TestInitOrder.stat1);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
str = "something";
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
private static final int stat1 = 10;
static final String str2 = "sdfff";
static String str = "crap";
private static int stat2 = 19;
static final Second second = new Second();
static final int lazy;
static {
lazy = 20;
}
static {
System.out.println(TestInitOrder.str2);
System.out.println(TestInitOrder.stat2);
System.out.println(TestInitOrder.str);
System.out.println(TestInitOrder.lazy);
System.out.println(TestInitOrder.second);
}
public static void main(String args[]) {
}
}
class Second {
public Second() {
System.out.println(TestInitOrder.second);
}
}
According to Java Language Specification, from section 4.12.5:
Every variable in a program must have a value before its value is used:
- Each class variable, instance variable, or array component is initialized with a default value when it is created
(The following lines from the specification specify the default value for all the types, basically some form of 0, such as 0
, 0.0d
, null
, false
, etc.)
So before the class is initialized (due to one of these reasons), the variables will hold an initial value.
According to the detailed initialization procedure (only the interesting steps are quoted here, and emphasis mine):
6.
[...] Then, initialize the final
class variables and fields of interfaces whose values are compile-time constant expressions (§8.3.2.1, §9.3.1, §13.4.9, §15.28).
[...]
9.
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
Let us look at step 6, with the 4 final
class variables: stat1
, str2
, second
, lazy
.
Since 10
is constant expression, and so is "sdfff"
, and due to the order of execution, it is not possible to observe the initial value for str2
and stat1
. In order to make an observation, the earliest you can do is in step 9.
The case of second
demonstrate that when the right hand side is not a compile-time constant expression, so its initial value is visible.
The case of lazy
is different, since the assignment is done in static block, and hence happen in step 9 - so it is possible to observe its initial value. (Well, the compiler checks carefully that lazy
is assigned exactly once).
After the initialization of final class variables with compile-time constant expression comes the execution of static blocks and the rest of the initializers.
As you can see from the example, the static blocks and initialization happens according to textual order - demonstrated with the use of str
variable - it is first printed out as null
, then something
, then crap
.