初始化场变量

som*_*guy 2 java field default-value

public class Foo {
    private int var;

    public Foo() {
        var = 10;
    }
}
Run Code Online (Sandbox Code Playgroud)

在此代码段中,var首先会为其分配一个默认值,然后重新分配给10,还是直接分配给10而不分配默认值?

有点琐碎的问题,但我很好奇.

mha*_*ler 5

如果查看反编译的字节代码Foo.class,您会注意到以下内容:

  • 类的构造函数本身只分配值10(bipush和putfield).类的构造函数不首先分配0然后分配10.
  • 无论何时访问,VM都会为该字段设置默认值0 - 无论从哪个代码开始.因此,此默认值不会显示在任何位置 - 至少不会出现在类的字节码或其他通过反射访问字段的类中.原始默认值将烘焙到VM中.
  • 显式设置默认值将产生不同的字节码,请参见第二个示例.

.

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
Run Code Online (Sandbox Code Playgroud)

如果你写下面的内容:

public class Foo {
    private int var = 0;

    public Foo() {
        var = 20;
    }
}
Run Code Online (Sandbox Code Playgroud)

字节码将是:

 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
Run Code Online (Sandbox Code Playgroud)

下一个示例显示访问变量仍然不会导致任何值的赋值:

public class Foo {
    private int var;

    public Foo() {
        System.out.println(var);
        var=10;
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码将打印,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
Run Code Online (Sandbox Code Playgroud)