If you look at the decompiled byte code of Foo.class, you will notice the following:
- The class' constructor itself only assigns the value 10 (bipush and putfield). The class's constructor does not first assign 0 and then 10.
- The VM will have a default value of 0 for the field whenever it is accessed - no matter from which code. So this default value will not show up anywhere - at least not in the bytecode of the class or other classes which access the field for example by reflection. Primitive default values are baked into the VM.
- Explicitly setting the default will produce different bytecode, see second example.
.
public class Foo {
private int var;
public Foo();
0 aload_0 [this]
1 invokespecial java.lang.Object() [10]
4 aload_0 [this]
5 bipush 10
7 putfield Foo.var : int [12]
10 return
If you write the following:
public class Foo {
private int var = 0;
public Foo() {
var = 20;
}
}
the bytecode will be:
0 aload_0 [this]
1 invokespecial java.lang.Object() [10]
4 aload_0 [this]
5 iconst_0
6 putfield Foo.var : int [12]
9 aload_0 [this]
10 bipush 20
12 putfield Foo.var : int [12]
15 return
The next example shows that accessing the variable will still not lead to an assignment of any value:
public class Foo {
private int var;
public Foo() {
System.out.println(var);
var=10;
}
}
This code will print 0 because getField Foo.var at opcode 8 will push "0" onto the operand stack:
public Foo();
0 aload_0 [this]
1 invokespecial java.lang.Object() [10]
4 getstatic java.lang.System.out : java.io.PrintStream [12]
7 aload_0 [this]
8 getfield Foo.var : int [18]
11 invokevirtual java.io.PrintStream.println(int) : void [20]
14 aload_0 [this]
15 bipush 10
17 putfield Foo.var : int [18]
20 return