为什么静态块无法访问它之后定义的静态变量

我已经检查了字段初始化期间的转发引用,这是@assylias的答案,但我仍然没有得到为什么的答案。

为什么静态块可以分配在其之后声明的静态变量,但不能访问它?

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

        }

    }

这是因为:该值尚未初始化,因此我们只是明确禁止您使用它?还是有一些与安全有关的东西我不知道?


更新

这不是关于这个问题的重复


为什么使用类名访问时不会发生这种情况?


这个问题是关于我们为什么有这个设计?目的何在?


噜噜哒
浏览 150回答 3
3回答

HUWWW

静态字段根据其在代码中的显示顺序进行初始化。所以,当你给变量赋值时,你只需对编译器说:“嘿,伙计,当你初始化这个变量时,把它的值设置为......”。但是在它被初始化之前,你不能使用它,因为它根本不存在。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规范不允许这样做。

qq_遁去的一_1

经过进一步的阅读,我认为帕维尔在这一点上并不完全准确,正如@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.ij = MyClass.i + 5具体来说,如果满足以下所有条件,则为编译时错误:类或接口 C 中类变量的声明在使用类变量后以文本方式出现;该用法是 C 的类变量初始值设定项或 C 的静态初始值设定项中的简单名称;使用不在作业的左侧;C 是包含用法的最内层类或接口。在这个答案中已经有详细的讨论。为了结束它,我认为这将是可预测的行为添加这些限制。8.3.3中再次指出了另一个官方目的。字段初始化期间的正向引用。这些限制旨在捕获编译时循环初始化或其他格式错误的初始化。

莫回无

这同样适用于非静态成员。您可以在实例初始值设定项块中为它们赋值,但在初始化之前不能使用它们。class Parent {    {        x = 3; // works fine        // System.out.println(x); // gives compilation error.    }    int x = 0;    public static void main(String[] args) {    }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java