Если вы посмотрите на декомпилированный байт-код Foo.class
, вы заметите следующее:
- Сам конструктор класса присваивает только значение 10 (bipush и putfield).Конструктор класса сначала не присваивает 0, а затем 10.
- Виртуальная машина будет иметь значение по умолчанию 0 для поля при каждом обращении к нему, независимо от того, из какого кода.Таким образом, это значение по умолчанию нигде не будет отображаться - по крайней мере, в байт-коде класса или других классов, которые обращаются к полю, например, с помощью отражения.Примитивные значения по умолчанию запекаются в ВМ.
- Явная установка значения по умолчанию приведет к созданию другого байт-кода, см. Второй пример.
.
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
Если вы пишетеследующее:
public class Foo {
private int var = 0;
public Foo() {
var = 20;
}
}
байт-код будет:
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
Следующий пример показывает, что доступ к переменной по-прежнему не приведет к присвоению какого-либо значения:
public class Foo {
private int var;
public Foo() {
System.out.println(var);
var=10;
}
}
Этот код будет печатать 0
, потому что getField Foo.var
с кодом операции 8 поместит «0» в стек операндов:
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