【问题标题】:How static block in java works? [duplicate]java中的静态块如何工作? [复制]
【发布时间】:2021-09-23 05:32:10
【问题描述】:

据我所知,静态字段和块是在一个类中从上到下处理的。我的意思是,必须先声明一个字段(静态字段),然后才能在静态块中使用它。必须首先声明静态字段,然后是修改该静态字段的静态块。对吧?

像这样:

private static Map<String, Object> map = new HashMap<>();
static {
    map.put("key", "value");
}

然后编译。如果我们像这样颠倒顺序:

static {
    map.put("key", "value");
}
private static Map<String, Object> map = new HashMap<>();

编译失败。

但是,如果我这样写。

static {
    map = new HashMap<>();
}
private static Map<String, Object> map;

成功了?!有人知道发生了什么吗?如果我为 map 分配一个新对象并不介意,但如果我在地图上放一些东西,它会编译失败。

请给我一个合理的答案。

【问题讨论】:

    标签: java static-methods


    【解决方案1】:

    Java 语言规范中提到了不允许在静态初始化程序中使用map 的理由:

    §12.4.1:

    静态初始化程序和类变量初始化程序按文本顺序执行,并且不能引用在使用后以文本形式出现的类中声明的类变量,即使这些类变量在范围内。 此限制旨在在编译时检测大多数循环或其他格式错误的初始化。

    由于初始化程序以文本顺序运行,静态初始化程序将在new HashMap&lt;&gt;() 之前运行,因此当map.put 执行时,map 将不会在那时初始化。显然,这是“畸形”。

    另一方面,如果你在静态初始化器中做了map = new HashMap&lt;&gt;();,你只是初始化map。那里没有错!注意,从上到下处理的是变量initialisers=之后的东西)。只要它们在scope 中,您总是可以看到前面以文本形式声明的声明map 的字段声明在这两种情况下都在范围内。

    §8.3.3 中进一步规定了允许和不允许的精确规则:

    在使用后以文本形式出现的类变量的使用有时会受到限制,即使这些类变量在范围内。具体来说,如果以下所有条件都为真,则为编译时错误:

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

    • 使用是 C 的类变量初始化器或 C 的静态初始化器中的简单名称;

    • 用法不在作业的左侧;

    • C 是包含使用的最内层类或接口。

    注意第三点 - 只有在 LHS 上使用 not 时才会出错!

    【讨论】:

      猜你喜欢
      • 2012-09-15
      • 2011-02-25
      • 1970-01-01
      • 2013-07-14
      • 2014-02-19
      • 2019-01-28
      • 2016-10-05
      • 1970-01-01
      • 2012-07-06
      相关资源
      最近更新 更多