[英]final variable initialized first
我在这里阅读这个问题: Java:初始化静态最终字段的顺序是什么?
根据答案
“除了最终的类变量和接口的字段,其值是编译时常量首先被初始化......”
我认为这是不正确的,因为以下将失败:
static {
String y = x;
}
public static final String x = "test";
在静态块中,无法识别x
。 如果答案是正确的,有人可以评论吗?
初始化顺序不会改变JLS在各种情况下声明变量之前不允许引用变量的事实。 这在JLS§8.3.3中描述:
使用声明在使用后以文本形式出现的类变量有时会受到限制,即使这些类变量在范围内(第6.3节)。 具体来说,如果满足以下所有条件,则为编译时错误:
在使用类变量之后,类或接口C中的类变量声明以文本形式出现;
在C的类变量初始化程序或C的静态初始化程序中使用是一个简单的名称;
使用不在作业的左侧;
C是封闭使用的最内层类或接口。
这就是你的代码得到这个编译erorr的原因:
错误:非法转发参考
首先初始化作为常量变量的静态字段的声明确实在JLS§12.4.2中定义:
否则,记录当前线程正在进行C的Class对象初始化并释放LC的事实。
然后,初始化C的静态字段,它们是常量变量(§4.12.4,§8.3.2,§9.3.1)。
...
- 接下来,按文本顺序执行类的类变量初始值设定项和类的静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样。
如您所见,常量变量在步骤6中初始化,但在步骤9中初始化。
这表明了这种行为:
public class Example {
static String y;
static {
y = foo();
}
static String foo() {
return x.toUpperCase();
}
public static final String x = "test";
public static void main(String[] args) throws Exception {
System.out.println(x);
System.out.println(y);
}
}
编译并输出:
test TEST
如果你更改了x
行,那么它就不再是常数了:
public static final String x = Math.random() < 0.5 ? "test" : "ing";
它编译,但随后将失败,因为x
是null
为y = foo();
。
为避免疑义:我不建议使用方法来初始化这样的字段。 :-)
正如这个答案所述:
......它们按照它们出现在源中的顺序进行初始化。
你是绝对正确的,你的例子失败了,因为你试图使用在使用之后声明的变量。 由于静态块是按源代码的顺序执行的,因此您绝对正确,应该建议并编辑该答案,因为此语句无效:
除了最后的类变量...首先被初始化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.