3 回答
TA贡献1874条经验 获得超12个赞
静态字段根据其在代码中的显示顺序进行初始化。
所以,当你给变量赋值时,你只需对编译器说:“嘿,伙计,当你初始化这个变量时,把它的值设置为......”。但是在它被初始化之前,你不能使用它,因为它根本不存在。i
更新:
正如James Gosling,Bill Joy,Guy Steele和Gilad Bracha在“Java语言规范”一书中所说:
这些限制旨在捕获编译时循环初始化或其他格式错误的初始化。
请考虑以下情况:
static {
i = 2;
j = i + 5; //should it be 7 or 15?
}
static int i = 10;
static int j;
变量应该是 7 还是 15?如果它是7,那么我们已经初始化了两次变量,这是不可能的,因为该字段是静态的。如果是15,那么这意味着什么?jii = 2;
这段代码是模棱两可的,所以Java规范不允许这样做。
TA贡献1725条经验 获得超7个赞
经过进一步的阅读,我认为帕维尔在这一点上并不完全准确,正如@Holger在评论中指出的那样。
我们已经初始化了两次i变量,这是不可能的,因为该字段是静态的。
与 12.4.2.详细的初始化过程指出
对于每个类或接口 C,都有一个唯一的初始化锁 LC。从 C 到 LC 的映射由 Java 虚拟机实现自行决定。
我认为初始化两次对类初始值设定项本身是可以的,只要它对调用客户端只有一次。
但是Pavel提供的演示仍然站稳了脚跟,所以我基本上只是在这里重用它,但有不同的解释。
static {
i = 2;
j = i + 5;
// no one knows whether "i" here initialized properly here
}
static int i = 10;
static int j;
但是当你直接在 中使用时,编译器会知道它会像8.3.3一样好。字段初始化期间的正向引用,详细说明了四个条件。MyClass.i
j = MyClass.i + 5
具体来说,如果满足以下所有条件,则为编译时错误:
类或接口 C 中类变量的声明在使用类变量后以文本方式出现;
该用法是 C 的类变量初始值设定项或 C 的静态初始值设定项中的简单名称;
使用不在作业的左侧;
C 是包含用法的最内层类或接口。
在这个答案中已经有详细的讨论。
为了结束它,我认为这将是可预测的行为添加这些限制。8.3.3中再次指出了另一个官方目的。字段初始化期间的正向引用。
这些限制旨在捕获编译时循环初始化或其他格式错误的初始化。
TA贡献1865条经验 获得超7个赞
这同样适用于非静态成员。您可以在实例初始值设定项块中为它们赋值,但在初始化之前不能使用它们。
class Parent {
{
x = 3; // works fine
// System.out.println(x); // gives compilation error.
}
int x = 0;
public static void main(String[] args) {
}
}
添加回答
举报