由于多态性而调用
a.print()打印。调用的方法取决于的运行时类型,即。何时调用无关紧要;多态总是适用。
4
a``B
两次都调用
B的
A的构造函数,由中的默认构造函数调用
B。另外一次是您显式致电
main。
究其原因,第一印刷产量
0,而不是
4因为在那个时候
A仍在建设。也就是说,
A构造函数仍在执行。在超类构造函数返回之前,子类中尚未初始化任何东西,甚至变量初始化器也没有初始化。该值
4在超类构造函数完成之后但在其余子类构造函数完成之前分配。由于变量初始值设定项尚未运行,因此默认值
0(将
false用于
booleans和
null对象)是
i第一次打印时的值。
JLS的第12.5节列出了此订单:
在返回对新创建对象的引用作为结果之前,使用以下过程处理指示的构造函数以初始化新对象:
- 将构造函数的参数分配给此构造函数调用的新创建的参数变量。
2.
如果此构造函数以同一个类中的另一个构造函数的显式构造函数调用(第8.8.7节)开头(使用此方法),则使用相同的五个步骤评估参数并递归处理该构造函数调用。如果该构造函数调用突然完成,则该过程由于相同的原因而突然完成;否则,请继续执行步骤5。3.
此构造函数并不以对同一个类中的另一个构造函数的显式构造函数调用(使用此函数)开头。如果此构造函数用于Object以外的其他类,则此构造函数将以显式或隐式调用超类构造函数(使用super)开始。使用这五个相同的步骤来递归评估超类构造函数调用的参数和过程。如果该构造函数调用突然完成,则出于相同原因,此过程也会突然完成。否则,请继续执行步骤4。
执行 此类 的实例初始化器和实例变量初始化器
,并按照从左到右的顺序将实例变量初始化器的值在文本中显示在该类的源代码中,并将它们分配给相应的实例变量。如果执行这些初始化程序中的任何一个导致异常,则不会再处理其他初始化程序,并且该过程会因相同的异常而突然完成。否则,请继续执行步骤5。执行此构造函数的其余部分。如果该执行突然完成,则出于相同原因,此过程也会突然完成。否则,此过程将正常完成。
(强调粗体)
这是为什么调用一个可以从构造函数中覆盖的方法不是一个好主意的示例。子类状态尚未初始化。



