初始化序列在JLS
12.5中指定:
- 首先,为新对象分配内存
- 然后,将对象中的所有实例变量(包括在此类及其所有超类中定义的实例变量)初始化为其默认值。
- 最后,调用构造函数。
规范的相关部分是:
…
如果没有足够的空间为该对象分配内存,则该类实例的创建将突然完成,并显示OutOfMemoryError。
否则,新对象中的所有实例变量(包括在超类中声明的实例变量)都将初始化为其默认值(第4.12.5节)。在返回对新创建对象的引用作为结果之前,使用以下过程 处理指示的构造函数 以初始化新对象:
…
这是永远不要
final从构造函数调用非方法的原因之一:该方法可能会被子类覆盖,在这种情况下,该方法将在子类有机会设置该方法可能需要的状态之前被调用。考虑以下示例:
public class Super { private final int superValue; protected Super() { superValue = getSuperValue(); } protected int getSuperValue() { return 1; } @Override public String toString() { return Integer.toString(superValue); }}public class Sub extends Super { private final int superValueOverride; public Sub(int value) { this.superValueOverride = value; } @Override protected int getSuperValue() { return superValueOverride; } public static void main(String[] args) { Super s = new Sub(2); System.out.println(s); }}看起来
s.superValue应该是2,对不对?毕竟,要
Sub重写
getSuperValue()以返回的值
superValueOverride,该值被初始化为2。但是,该方法在的任何
Sub字段初始化之前(而不是其默认值)被调用,因此
s.superValue实际上是0(默认值
superValueOverride)。
这是更奇怪的,因为
superValueOverride是
final,但它似乎改变了它的价值!
Super调用时为0
getSuperValue(),只有在
Super构造函数完成后才为其分配最终值2(或传递给构造函数的任何值)。



