我无法理解初始化的顺序。这是我假设的顺序:
*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节)规定,在声明变量之前,可以在表达式的左侧使用变量,即赋值,但不能在右侧使用。
所有变量都初始化为默认值,然后显式初始化程序和匿名块按照在源文件中找到的顺序运行。最后调用构造函数。
Statics在第一次使用类时只运行一次。
编译错误似乎是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中找到这方面的参考资料。