Ale*_*exx 6 java final field initialization
public class Main {
static final int alex=getc();
static final int alex1=Integer.parseInt("10");
static final int alex2=getc();
public static int getc(){
return alex1;
}
public static void main(String[] args) {
final Main m = new Main();
System.out.println(alex+" "+alex1 +" "+alex2);
}
}
Run Code Online (Sandbox Code Playgroud)
有人能告诉我为什么会这样打印:0 10 10?我知道它是一个静态的最终变量,它的值不应该改变,但是理解编译器如何初始化字段有点困难.
JLS 8.3.2.3 “初始化期间对字段使用的限制”涵盖了这种情况。
JLS 规则允许在您的问题中使用,并声明第一次调用getc()将返回alex.
但是,规则不允许使用未初始化的变量;例如
int i = j + 1;
int j = i + 1;
Run Code Online (Sandbox Code Playgroud)
被禁止。
重新回答一些其他的答案。这不是 Java 编译器“无法弄清楚”的情况。编译器严格执行 Java 语言规范指定的内容。(或者换一种说法,编译器会被写入到检测圆你的榜样,并把它编译错误。但是,如果这样做,将被拒绝有效的Java程序,因此不会成为符合Java 编译器。)
在评论中,您说明了这一点:
... final 字段总是必须在编译或运行时在对象创建之前初始化。
这是不正确的。
实际上有两种final字段:
确实在编译时评估了所谓的“常量变量”。(常量变量是“原始类型或字符串类型的变量,它是最终的并使用编译时常量表达式进行初始化” - 参见 JLS 4.12.4。)。这样的字段在您访问它时将始终被初始化......对此处不相关的某些复杂情况进行模数。
其他final字段由JLS指定的顺序初始化,因此,是可以看到该字段的值已初始化之前。上的限制final变量是它们必须被初始化一次且仅一次在类初始化(一static)或在对象初始化。
最后,这个东西是非常“角落案例”的行为。典型的编写良好的类final在初始化之前不需要访问字段。