我对下面的代码感到困惑,我预计它会给出错误或答案将是 10,但它给出了 20 怎么办?
public class test {
public static void main(String[] args) {
System.out.println(x);
}
static{
x=10;
}
static int x=20;
}
我对下面的代码感到困惑,我预计它会给出错误或答案将是 10,但它给出了 20 怎么办?
public class test {
public static void main(String[] args) {
System.out.println(x);
}
static{
x=10;
}
static int x=20;
}
它在 JLS 的第 12.4.2 节中指定,其中提供了类初始化的详细信息:
接下来,按照文本顺序执行类的类变量初始化程序和静态初始化程序,或者接口的字段初始化程序,就好像它们是一个单独的块一样。
变量初始化器 ( ) 出现在程序文本中x = 20
的静态初始化器(包含 的块)之后。x = 10
因此,初始化结束时的值为 20。
如果您交换订单轮次以使变量初始值设定项首先出现,您将看到 10。
我强烈建议您尽可能避免编写依赖于文本排序的代码。
编辑:该变量仍然可以在静态初始化程序中使用,因为它在范围内 - 就像您可以在比变量更早声明的方法中使用实例变量一样。但是,第 8.3.2.3 节对此给出了一些限制:
仅当成员是类或接口 C 的实例(分别为静态)字段并且满足以下所有条件时,成员的声明才需要在使用之前以文本形式出现:
该用法发生在 C 的实例(分别为静态)变量初始化器或 C 的实例(分别为静态)初始化器中。
用法不在作业的左侧。
用法是通过一个简单的名称。
C 是包含用法的最里面的类或接口。
如果不满足上述四个要求中的任何一个,则为编译时错误。
因此,如果您将静态初始化程序更改为:
static {
System.out.println(x);
}
那么你会得到一个错误。
但是,您现有的静态初始化程序x
的使用方式确实符合所有限制。
在静态中,如果一个值被更改一次,那么它将一直生效。所以你得到了20。
如果你这样写
public class test {
static int x=20;
public static void main(String[] args) {
System.out.println(x);
}
static{
x=10;
}
}
然后它将打印 10。