最终变量首先初始化
final variable initialized first
我正在阅读这里的问题:Java : in what order are static final fields initialized?
根据回答
"except that final class variables and fields of interfaces whose
values are compile-time constants are initialized first ..."
我认为这是不正确的,因为以下会失败:
static {
String y = x;
}
public static final String x = "test";
在静态块中,x
不被识别。如果答案正确,有人可以发表评论吗?
如this answer所述:
... they are initialized in the order in which they appear in the source.
你完全正确,你的例子失败了,因为你试图使用一个在使用之后声明的变量。由于静态块是按源代码的顺序执行的,因此您是绝对正确的,应该建议并编辑该答案,因为此语句无效:
except that final class variables ... are initialized first.
初始化 的顺序不会改变 JLS 不允许您在各种情况下声明变量之前引用变量的事实。这在 JLS§8.3.3:
中有描述
Use of class variables whose declarations appear textually after the use is sometimes restricted, even though these class variables are in scope (§6.3). Specifically, it is a compile-time error if all of the following are true:
The declaration of a class variable in a class or interface C appears textually after a use of the class variable;
The use is a simple name in either a class variable initializer of C or a static initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
这就是您的代码出现此编译错误的原因:
error: illegal forward reference
作为常量变量的静态字段先初始化的说法确实在JLS§12.4.2中定义:
Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.
Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).
...
- Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
如您所见,常量变量在第 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
在 y = foo();
时是 null
。
为免生疑问:我不建议使用方法来初始化这样的字段。 :-)
我正在阅读这里的问题:Java : in what order are static final fields initialized?
根据回答
"except that final class variables and fields of interfaces whose values are compile-time constants are initialized first ..."
我认为这是不正确的,因为以下会失败:
static {
String y = x;
}
public static final String x = "test";
在静态块中,x
不被识别。如果答案正确,有人可以发表评论吗?
如this answer所述:
... they are initialized in the order in which they appear in the source.
你完全正确,你的例子失败了,因为你试图使用一个在使用之后声明的变量。由于静态块是按源代码的顺序执行的,因此您是绝对正确的,应该建议并编辑该答案,因为此语句无效:
except that final class variables ... are initialized first.
初始化 的顺序不会改变 JLS 不允许您在各种情况下声明变量之前引用变量的事实。这在 JLS§8.3.3:
中有描述Use of class variables whose declarations appear textually after the use is sometimes restricted, even though these class variables are in scope (§6.3). Specifically, it is a compile-time error if all of the following are true:
The declaration of a class variable in a class or interface C appears textually after a use of the class variable;
The use is a simple name in either a class variable initializer of C or a static initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
这就是您的代码出现此编译错误的原因:
error: illegal forward reference
作为常量变量的静态字段先初始化的说法确实在JLS§12.4.2中定义:
Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.
Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).
...
- Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
如您所见,常量变量在第 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
在 y = foo();
时是 null
。
为免生疑问:我不建议使用方法来初始化这样的字段。 :-)