执行初始化程序块和变量定义等的顺序是什么? (在java中)

我在理解初始化发生的顺序时遇到问题。 这是我假设的顺序:

*Once per 1. Static variable declaration 2. Static block *Once per object 3. variable declaration 4. initialization block 5. constructor 

但根据这段代码,我显然是错的:

  class SomethingWrongWithMe { { b=0; //no. no error here. int a = b; //Error: Cannot reference a field before it is defined. } int b = 0; } 

如果我这样做,错误就会消失:

  class SomethingWrongWithMe { int b = 0; { b=0; int a = b; //The error is gone. } } 

我无法弄清楚为什么没有错误

  b=0; 

Java语言规范(第8.3.2.3节)说你可以在表达式的左侧使用变量,即在声明它之前赋值给它,但是你不能在右边使用它。

所有变量都初始化为其默认值,然后显式初始化器和匿名块按源文件中的顺序运行。 最后调用构造函数。

静态只在第一次使用类时运行一次。

编译错误似乎是Java的规则,而不是在每种情况下都必须有意义的事情。

变量定义不是在“之前”块之前完成的。 它们都是按照定义的顺序同时完成的

 class SomethingWrongWithMe { { b = debug("block 1"); } int b = debug("define"); { b = debug("block 2"); } private int debug(String str) { System.out.println(str); return 0; } } 

产量

 block 1 define block 2 

首先,您的假设或多或少是正确的,除了声明(初始化,例如int b = 0 )和实例初始化程序块按它们被写入的顺序执行的事实。

 int b = 0; // executed first { b = 1; // executed second } int a = b; // executed third 

另请注意, 声明int b不会被执行 。 声明只声明了变量的存在。

至于你得到的错误(或者说你没有得到的错误)我同意它看起来很奇怪。 我假设编译器处理引用表达式中的变量并以不同方式为其赋值。 当写入实例初始值设定项中的变量时,它只检查变量是否存在,而当从中读取变量时,它需要在实例初始化程序块之上声明它。 我会看看我是否可以在JLS中找到相关参考。