java - 默认变量值与默认初始化

标签 java bytecode compiler-optimization

我们都知道,根据JLS7 p.4.12.5每个实例变量都使用默认值进行初始化。例如。 (1):

public class Test {
    private Integer a;  // == null
    private int b;      // == 0
    private boolean c;  // == false
}

但我一直认为,这样的类实现(2):

public class Test {
    private Integer a = null;
    private int b = 0;
    private boolean c = false;
}

绝对等于示例(1)。我预计,复杂的 Java 编译器会发现 (2) 中的所有这些初始化值都是多余的并忽略它们。

但是突然间,对于这两个类,我们有两个不同的字节码。

例如(1):

   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

例如(2):

   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   aload_0
   5:   aconst_null
   6:   putfield    #2; //Field a:Ljava/lang/Integer;
   9:   aload_0
   10:  iconst_0
   11:  putfield    #3; //Field b:I
   14:  aload_0
   15:  iconst_0
   16:  putfield    #4; //Field c:Z
   19:  return

问题是:为什么?但这是显而易见的需要优化的事情。原因是什么?

UPD:我使用 Java 7 1.7.0.11 x64,没有特殊的 javac 选项

最佳答案

不,它们并不等同。在对象实例化时立即分配默认值。当父类(super class)构造函数被调用时,字段初始值设定项中的赋值就会发生...这意味着在某些情况下您可以看到差异。示例代码:

class Superclass {
    public Superclass() {
        someMethod();
    }

    void someMethod() {}
}

class Subclass extends Superclass {
    private int explicit = 0;
    private int implicit;

    public Subclass() {
        System.out.println("explicit: " + explicit);
        System.out.println("implicit: " + implicit);
    }

    @Override void someMethod() {
        explicit = 5;
        implicit = 5;
    }
}

public class Test {
    public static void main(String[] args) {
        new Subclass();
    }
}

输出:

explicit: 0
implicit: 5

在这里您可以看到,在Superclass构造函数完成之后但在子类构造函数body之前,显式字段初始化将explicit的值“重置”回0 执行。 implicit 的值仍然具有在从 Superclass 构造函数对 someMethod 的多态调用中分配的值。

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

相关文章:

c# - .Max() 与 OrderByDescending().First()

警告 “dereferencing type-punned pointer will break strict-aliasing rules” 的后果

java - 如何从 4 个 Excel 工作表中用 Java 数据创建单个数据库表?

java - 有没有办法查看Java底层的C代码?

scripting - 反编译 Lua 字节码的最佳工具?

java - 方法签名中带或不带synchronized关键字的方法具有相同的字节码

c++ - const 右值引用是否允许对编译器进行额外优化?

Java并行同步2个线程

java - 如何通过Java抓取CSV文件中的货币格式数字

java - Maven 构建失败