public class Dog {
public static Dog dog = new Dog();
static final int val1 = -5;
static int val2 = 3;
public int val3;
public Dog() {
val3 = val1 + val2;
}
public static void main(String[] args) {
System.out.println(Dog.dog.val3);
}
}
The output is -5
From this result, it seems that the initialization of val2
is before the completion of dog
member and its instantiating.
Why is this order like this?
It makes sense to initialize the variable at declaration to avoid redundancy. It also makes sense to consider final variables in such a situation. If you know what value a final variable will have at declaration, it makes sense to initialize it outside the constructors.
Note: It is not necessary to declare fields at the beginning of the class definition, although this is the most common practice. It is only necessary that they be declared and initialized before they are used.
All static members are always initialized before any class constructor is being called.
Class-level fields (instance or static fields) get default values assigned to them. This means that if the constructor or instance (or static) initialization blocks don't explicitly initialize these fields, the default values will remain.
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
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.
Variable declaration sequence. The static final int val1
is initialized first because it is a constant. However static int val2
is still 0
at the time public static Dog dog = new Dog();
is instantiated.
What is happening..
The first line that is executing is this public static Dog dog = new Dog();
.
Now, there are 2 things that must be kept in mind.
final int
makes it a compile time constant. So, -5
is already hard-coded into your code.
The call to new Dog()
is done and the constructor is called which sets the value to 0
+ -5
= -5
.
change val2
to final
then you will see the difference (you will get -2
as answer.)
Note : static fields are initialized as and how they are encountered.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With