为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

噜噜哒 2022-08-17 16:06:53
我已经检查了字段初始化期间的转发引用,这是@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        }    }这是因为:该值尚未初始化,因此我们只是明确禁止您使用它?还是有一些与安全有关的东西我不知道?更新这不是关于这个问题的重复为什么使用类名访问时不会发生这种情况?这个问题是关于我们为什么有这个设计?目的何在?
查看完整描述

3 回答

?
HUWWW

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规范不允许这样做。


查看完整回答
反对 回复 2022-08-17
?
qq_遁去的一_1

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.ij = MyClass.i + 5

具体来说,如果满足以下所有条件,则为编译时错误:

  1. 类或接口 C 中类变量的声明在使用类变量后以文本方式出现;

  2. 该用法是 C 的类变量初始值设定项或 C 的静态初始值设定项中的简单名称;

  3. 使用不在作业的左侧;

  4. C 是包含用法的最内层类或接口。

在这个答案中已经有详细的讨论。

为了结束它,我认为这将是可预测的行为添加这些限制。8.3.3中再次指出了另一个官方目的。字段初始化期间的正向引用

这些限制旨在捕获编译时循环初始化或其他格式错误的初始化。


查看完整回答
反对 回复 2022-08-17
?
莫回无

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) {


    }

}


查看完整回答
反对 回复 2022-08-17
  • 3 回答
  • 0 关注
  • 149 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信