If you move your dog instance in the end, you may find the output becomes -2
public class Dog {
static final int val1 = -5;// This is final, so will be initialized at compile time
static int val2 = 3;
public int val3;
public static Dog dog = new Dog();//move to here
public Dog() {
val3 = val1 + val2;
}
public static void main(String[] args) {
System.out.println(Dog.dog.val3);//output will be -2
}
}
The final fields(whose values are compile-time constant expressions) will beinitialized first, and then the rest will be executed at in textual order.
So , in your case when dog instance is initialized, static int val2
(0) is not initialized yet, while static final int val1
(-5) does since it is final.
http://docs.oracle.com/javase/specs/jls/se5.0/html/execution.html#12.4.2 states that:
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, except that
final class variables and fields of interfaces whose values are
compile-time constants are initialized first
Updated a newer doc
Here is the jdk7 version from http://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.2
final field is at step6:
Then, initialize the final class variables and fields of interfaces
whose values are compile-time constant expressions
while static field is at step 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.