java - java中的静态块如何工作?
问题描述
据我所知,静态字段和块是在一个类中从上到下处理的。我的意思是,必须先声明一个字段(静态字段),然后才能在静态块中使用它。必须首先声明静态字段,然后是修改该静态字段的静态块。正确的?
像这样:
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分配一个新对象并不介意,但是如果我在 map 上放一些东西,它就无法编译。
请给我一个合理的答案。
解决方案
map
Java语言规范中提到了不允许在静态初始化程序中使用的理由:
静态初始化器和类变量初始化器按文本顺序执行,并且不能引用在使用后以文本形式出现的类中声明的类变量,即使这些类变量在范围内。此限制旨在在编译时检测大多数循环或其他格式错误的初始化。
由于初始化程序以文本顺序运行,静态初始化程序将在 之前运行new HashMap<>()
,因此在map.put
执行map
时,此时不会被初始化。显然,这是“畸形”。
另一方面,如果你map = new HashMap<>();
在静态初始化器中做了,你只是在初始化 map
。那里没有错!请注意,从上到下处理的是变量初始化程序(后面的东西)。只要它们在范围内=
,您总是可以看到前面以文本形式声明的声明。的字段声明在这两种情况下都在范围内。map
§8.3.3进一步规定了允许和不允许的精确规则:
有时限制使用在使用后以文本形式出现声明的类变量,即使这些类变量在范围内。具体来说,如果以下所有条件都为真,则为编译时错误:
类或接口 C 中的类变量声明在使用类变量之后以文本形式出现;
use 是 C 的类变量初始化器或 C 的静态初始化器中的简单名称;
使用不在作业的左侧;
C 是包含使用的最内层类或接口。
注意第三点——只有在 LHS 上没有使用才会出错!
推荐阅读
- c++ - Traversal pointer in tree while insertion
- ios - 如何在 iOS swift 模块化应用程序中执行路由?
- c++ - 我找不到调整神经网络的正确方法
- datepicker - 日期选择器:任何一天的选择
- go - Closures in Golang - String not displayed
- java - 限制打开的最大文件大小
- python-3.x - uWSGI +nginx 设置 - Dash (Plotly) 部署
- javascript - 如何使用 opencv_contrib 构建自定义 opencv.js
- javascript - Highcharts: Drilldown from map to chart
- jmeter - JMeter:响应数据与预期不同