我有一个班级
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
理想情况下,块在构造函数之前执行,但是在构造函数之后调用内联初始化块。为什么呢?
答案 0 :(得分:16)
您正在创建Temp
的子类。对于每个类,任何实例初始值设定项都在构造函数体之前执行 - 但超类在子类初始化之前经历初始化。所以执行流程是:
Object
Object
Temp
Temp
我强烈建议你重构任何看起来像这样的代码 - 目的是为了清晰而不是聪明。
答案 1 :(得分:6)
JLS 12.5说明施工过程中发生事情的顺序(强调我的):
在对新创建的对象的引用之前返回为 结果,处理指示的构造函数以初始化new 使用以下过程对象:
(3)这个构造函数不是以同一个类中另一个构造函数的显式构造函数调用开始的(使用它)。如果 这个构造函数用于Object以外的类,然后是这个 构造函数将以a的显式或隐式调用开始 超类构造函数(使用超级)。 评估参数和 使用这些来递归地处理超类构造函数调用 相同的五个步骤。如果构造函数调用突然完成, 然后由于同样的原因,这个程序突然完成。除此以外, 继续第4步。
(4)为此类执行实例初始值设定项和实例变量初始值设定项,分配实例变量的值 初始化器到相应的实例变量中 从左到右的顺序,它们在源代码中以文本形式出现 为了上课。如果执行任何这些初始化程序导致 异常,然后没有处理进一步的初始化程序 程序突然完成同样的异常。除此以外, 继续第5步。
(5)执行此构造函数的其余部分。如果执行突然完成,则此过程突然完成 同样的道理。否则,此过程正常完成。
总而言之,超类构造函数(步骤3)在实例初始化器之前执行(步骤4)。两者都在“此构造函数的其余部分”(在您的示例中没有)之前执行。
答案 2 :(得分:2)
内联初始化块在您正在实例化的匿名类的基类的构造函数之后以及匿名类本身的空隐式构造函数之前调用。
答案 3 :(得分:2)
您实际创建的不是Temp
类实例,而是继承自Temp
的某个类的实例。
因此,首先调用Temp
初始值设定项(Temp
及其construstor中的无限块),然后调用无穷大类中的初始化函数。
答案 4 :(得分:1)
第1点:要清楚,你有两个实例初始值设定项:一个在Temp类中,另一个在main()方法中创建的匿名内部类中,该方法是Temp的子类。
第2点:实例初始值设定项实际上并未在构造函数之前运行。 Per the JLS, they're run during a constructor,在委托给超级构造函数之后,初始化实例字段并完成构造函数之前。
第3点:在您的代码中,每个初始化程序都在适当的时候正确执行。我认为你期望第二个与第一个同时执行,但那是不正确的,因为正如第1点所指出的,它们是两个不同类的初始化器。
第4点:你可能也会在静态initializers and instance initializers之间感到困惑。它们是两个不同的东西。
答案 5 :(得分:1)
在您的代码中
Temp t = new Temp(){
{
System.out.println(" instance initialize");
}
};
您正在创建扩展Temp类的匿名类的对象。
创建子类的对象:
initialize block from Superclass
constructor of Superclass
initialize block from Subclass
constructor of Subclass
答案 6 :(得分:0)
在完成任何其他操作之前,对象必须先在内存中。该对象在内存中构建,然后您的控制台打印发生。