Java静态初始化顺序
我试图发现初始化发生的顺序,或者说是为什么初始化按照这个顺序发生的原因。 给定代码:
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
而我完全不知道为什么会按这个顺序出现。 另外,如果我在m
的声明中删除了static
关键字,init块和构造函数都不会触发。 任何人都可以帮我解决这个问题吗?
我想你只是缺lessJLS的12.4.2节 ,其中包括:
接下来,按照文本顺序执行类的variables初始值设定项和静态初始值设定项或接口的字段初始值设定项,就好像它们是单个块一样。
“按原文顺序”部分是重要的一点。
如果将m
从静态variables更改为实例variables,那么该字段将不会通过类初始化进行初始化 – 只会通过实例初始化(即构build实例时)进行初始化。 此刻,这将导致堆栈溢出 – 创build一个实例需要创build另一个实例,这需要创build另一个实例等。
编辑:类似的部分12.5指定实例初始化,包括这些步骤:
执行此类的实例初始化程序和实例variables初始化程序,将实例variables初始化程序的值分配给相应的实例variables,按照从左到右的顺序,它们以文本forms显示在类的源代码中。 如果执行这些初始化程序中的任何一个都会导致exception,则不会执行进一步的初始化程序,并且此过程会以相同的exception突然完成。 否则,继续执行步骤5。
执行此构造函数的其余部分。 如果该执行突然完成,则此过程由于相同的原因而突然完成。 否则,此过程正常完成。
所以这就是为什么你在“主要构造者”之前看到“非静止块”的原因。