默认变量的值与初始化的默认值
我们都知道,根据JLS7第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."":()V 4: return
例如(2):
0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()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选项
不,他们不相同。 在对象实例化时立即分配默认值。 字段初始值设定项中的赋值发生在调用超类构造函数时…这意味着在某些情况下您可以看到差异。 示例代码:
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
在这里你可以看到显式字段初始化“重置” explicit
的值在Superclass
构造函数完成之后但在子类构造函数体执行之前返回到0。 implicit
值仍然具有在Superclass
构造函数对someMethod
的多态调用中指定的值。