Java 为什么静态块不能访问在它之后定义的静态变量
我已经检查过了,但仍然没有找到原因的答案 为什么静态块可以分配在它之后声明的静态变量,但不能访问它Java 为什么静态块不能访问在它之后定义的静态变量,java,java-8,static,static-block,Java,Java 8,Static,Static Block,我已经检查过了,但仍然没有找到原因的答案 为什么静态块可以分配在它之后声明的静态变量,但不能访问它 class Parent { static { i = 2; // valid // can only assign new value to it instead of accessing it? // System.out.println(i); // invalid - compile-error
class Parent {
static {
i = 2; // valid
// can only assign new value to it instead of accessing it?
// System.out.println(i); // invalid - compile-error
}
static int i = 0;
static {
i = 3; // valid
}
}
这是因为:该值尚未初始化,所以我们只是显式禁止您使用它?或者有什么和安全有关的事我不知道
更新
这不是一个重复的问题,这是关于
为什么使用类名访问时不会发生这种情况
这个问题是关于为什么我们有这个设计?出于什么目的?静态字段根据它们在代码中出现的顺序进行初始化 所以,当你给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;
j变量应该是7还是15?
如果是7,那么我们已经初始化了两次i变量,这是不可能的,因为该字段是静态的。如果是15,那么i=2是什么;什么意思
这段代码模棱两可,所以Java规范不允许这样做。进一步阅读后,我认为Pavel在这一点上并不十分准确,正如评论中所指出的那样 我们已经初始化了两次i变量,这是不可能的,因为该字段是静态的 正如报告所指出的那样 对于每个类或接口C,都有一个唯一的初始化锁LC。从C到LC的映射由Java虚拟机实现自行决定 我认为初始化两次对类初始值设定项本身来说是可以的,只要对调用的客户机来说只有一次 但帕维尔提供的演示仍然站在它的立场上,所以我基本上只是在这里重复使用它,但有不同的解释
static {
i = 2;
j = i + 5;
// no one knows whether "i" here initialized properly here
}
static int i = 10;
static int j;
但是,当您直接在j=MyClass.i+5中使用MyClass.i时,编译器就会知道这样就可以了,具体有四个条件
具体地说,如果以下所有情况都是错误的,则这是一个编译时错误
正确:
此时会出现类或接口C中的类变量声明
使用类变量后的文本形式
在C的类变量初始值设定项中使用一个简单的名称
或C的静态初始值设定项
使用不在作业的左侧
C是包含该用法的最内层类或接口
在这方面已经有了详细的讨论
最后,我认为这将是为可预测的行为添加这些限制。另一个官方目的再次在报告中指出
这些限制旨在在编译时捕获循环或其他格式错误的初始化
这同样适用于非静态构件。您可以在实例初始值设定项块中为它们赋值,但不能在初始化之前使用它们
class Parent {
{
x = 3; // works fine
// System.out.println(x); // gives compilation error.
}
int x = 0;
public static void main(String[] args) {
}
}
将出现@Lino提到的编译错误,因此您无法获得bytecode@Lino这段代码无法编译。没有要检查的字节码。不要在这里发表毫无意义的猜测。是的,这是因为它还没有初始化,这就是错误消息所说的,不是吗?可能重复@Hearen询问为什么要做出语言决定并不容易回答问题。这需要一位java开发人员非常深入的知识,除非Brian Goetz过来,否则我不确定这里是否有人能回答这个问题,并提供了一些解释。哇,非常感谢。我只是迷路了,不知道为什么这是不允许的。这个例子确实给了我线索。非常感谢你!Pavel“那么我们已经初始化了两次i变量,这是不可能的,因为该字段是静态的”啊,你为什么认为这是不可能的?您可以随意分配变量,除非它是最终变量。您可以轻松地编写静态int i=2,j=i+++5;静态{i+=3;}或更改j=i+5;在您自己的示例中,j=ClassName.i+5;在Java规范中是这样说的:在运行时,初始化器被计算,赋值在类初始化时执行一次。这里和这里关于引用变量的全名。在这种情况下,编译器确切地知道类已经初始化。这里讨论了这个问题: