java - 初始化字段变量

标签 java field default-value

public class Foo {
    private int var;

    public Foo() {
        var = 10;
    }
}

在这段代码中,是先给var赋一个默认值,然后重新赋给10,还是直接赋给10,不赋默认值?

有点微不足道的问题,但我很好奇。

最佳答案

如果您查看 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

如果你这样写:

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,因为操作码 8 处的 getField Foo.var 会将“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

关于java - 初始化字段变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4694073/

相关文章:

api - 在 Drupal 7 中设置和更新节点上字段内容的正确方法是什么?

java - 服务层静态对象字段有什么用

postgresql - Postgres 准备了具有不同字段的语句

php - MySQL 默认 date() + 14 天,对于一个列?

Angular 4 动态表单 - 如果未触及则为空值 - 如何获取这些显示的默认值?

java - 使用默认值初始化数组中的对象 - java

java - 如何在 Playframework 2.5 上启动并定期调用函数

java - 无法使用JPA在H2中创建表和加载数据

java - 用 Executor 替换 BlockingQueue + 守护线程

java - 在 Java 中编写递归方法时遇到问题