java中的内联初始化块

我上课了

public class MyMain{ public static void main(String... arg){ Temp t = new Temp(){ { System.out.println(" instance initialize"); } }; } } class Temp{ int i; { i=9; System.out.println("Static"+i); } Temp(){ System.out.println("Temp const "+i); } } 

当我执行main方法时输出到:

 Static9 Temp const 9 instance initialize 

理想情况下,块在构造函数之前执行,但是在构造函数之后调用内联初始化块。 为什么?

你正在创建一个Temp子类 。 对于每个类,任何实例初始值设定项都在构造函数体之前执行 – 但是超类在子类初始化之前进行初始化。 所以执行流程是:

  • Object初始化器
  • Object构造函数体
  • Temp初始化器
  • Temp构造函数体
  • 匿名类中的初始化器
  • 匿名类中的构造函数体(无)

我强烈建议你重构任何看起来像这样的代码 – 旨在澄清而不是聪明。

JLS 12.5详细说明了施工过程中发生的事情(强调我的):

在作为结果返回对新创建的对象的引用之前,处理指示的构造函数以使用以下过程初始化新对象:

(3)这个构造函数不是以同一个类中另一个构造函数的显式构造函数调用开始的(使用它)。 如果此构造函数用于Object以外的类,则此构造函数将以超类构造函数的显式或隐式调用开始(使用super)。 使用这五个相同的步骤评估参数并递归处理超类构造函数调用。 如果该构造函数调用突然完成,则由于同样的原因,此过程突然完成。 否则,继续执行步骤4。

(4) 为该类执行实例初始值设定项和实例变量初始值设定 ,将实例变量初始值设定项的值按从左到右的顺序分配给相应的实例变量,在这些顺序中,它们以文本方式出现在类的源代码中。 如果执行任何这些初始值设定项导致exception,则不会处理其他初始值设定项,并且此过程会突然完成同样的exception。 否则,继续步骤5。

(5) 执行此构造函数的其余部分。 如果该执行突然完成,则由于同样的原因,此过程突然完成。 否则,此过程正常完成。

总而言之,超类构造函数(步骤3)在实例初始化器之前执行(步骤4)。 两者都在“此构造函数的其余部分”(在您的示例中没有)之前执行。

内联初始化块在您正在实例化的匿名类的基类的构造函数之后以及匿名类本身的空隐式构造函数之前调用。

你实际创建的不是一个Temp类实例,而是一个inheritance自Temp一个非常类的实例。

因此,首先调用Temp初始值设定项( Temp及其construstor内部的无限块),然后调用anonimous类中的初始值设定项。

要点1:要清楚,您有两个实例初始值设定项:一个在Temp类中,另一个在main()方法中创建的匿名内部类中,该方法是Temp的子类。

第2点:实例初始值设定项实际上并不构造函数之前运行。 根据JLS,它们构造函数中运行 ,在委托给超级构造函数之后,在初始化实例字段和完成构造函数之前运行。

第3点:在您的代码中,每个初始化程序在适当的时间正确执行。 我认为你期望第二个与第一个同时执行,但这是不正确的,因为正如第1点所指出的,它们是两个不同类的初始化器。

第4点:您可能还会在静态初始化程序和实例初始化程序之间混淆。 他们是两个不同的东西。

在你的代码中

 Temp t = new Temp(){ { System.out.println(" instance initialize"); } }; 

您正在创建扩展Temp类的匿名类的对象。

创建子类的对象:

 initialize block from Superclass constructor of Superclass initialize block from Subclass constructor of Subclass 

在对其进行任何其他操作之前,该对象必须首先在内存中。 该对象在内存中构建,然后您的控制台打印发生。