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。

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

所以这就是为什么你在“主要构造者”之前看到“非静止块”的原因。