我正在尝试发现初始化发生的顺序,或者说是为什么初始化按此顺序发生的原因。鉴于代码:
public class Main {
{
System.out.printf("NON-STATIC BLOCK\n");
}
static{
System.out.printf("STATIC BLOCK\n");
}
public static Main m = new Main();
public Main(){
System.out.printf("MAIN CONSTRUCTOR\n");
}
public static void main(String... args) {
//Main m = new Main();
System.out.printf("MAIN METHOD\n");
}
}
输出:
STATIC BLOCK
NON-STATIC BLOCK
MAIN CONSTRUCTOR
MAIN METHOD
但是,在初始化块之前移动m
的声明会产生:
NON-STATIC BLOCK
MAIN CONSTRUCTOR
STATIC BLOCK
MAIN METHOD
我完全不知道它为什么会按此顺序出现。此外,如果我在static
的声明中删除m
关键字,则init块和构造函数都不会触发。任何人都可以帮我解决这个问题吗?
答案 0 :(得分:28)
我认为你只是缺少section 12.4.2 of the JLS,其中包括:
接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,就像它们是单个块一样。
“文本顺序”部分是重要的一点。
如果将m
从静态变量更改为实例变量,则 class 初始化不会初始化该字段 - 它只能由实例初始化初始化(即构造实例时)。目前,这会导致堆栈溢出 - 创建一个实例需要创建另一个实例,这需要创建另一个实例,等等。
编辑:类似地section 12.5指定实例初始化,包括以下步骤:
为此类执行实例初始值设定项和实例变量初始值设定项,将实例变量初始值设定项的值按从左到右的顺序分配给相应的实例变量,在这些顺序中它们以文本方式出现在源代码中类。如果执行任何这些初始值设定项导致异常,则不会处理其他初始化程序,并且此过程会突然完成同样的异常。否则,请继续步骤5.
执行此构造函数的其余部分。如果执行突然完成,则此过程突然完成,原因相同。否则,此过程正常完成。
这就是为什么你在“MAIN CONSTRUCTOR”之前看到“NON-STATIC BLOCK”的原因。