我想创建一个enum每个常量Map与之关联的位置.我完成了这个,给每个常量一个实例初始化器,如下所示:
import java.util.HashMap;
import java.util.Map;
public enum Derp {
FOO {{
mMap.put("bar", 1);
}};
// cannot be private
protected final Map<String, Integer> mMap = new HashMap<>();
}
Run Code Online (Sandbox Code Playgroud)
我发现如果mMap是private,则无法在实例初始化程序中引用它.错误是Cannot make a static reference to the non-static field mMap.在我发生这种情况之前,我咨询了JLS§8.9.2,其中部分说:
对于构造函数,实例初始化程序块或枚举常量的实例变量初始化程序表达式来说,它是一个编译时错误,它
e指向e或向右侧声明的相同类型的枚举常量e.
我是不是通过FOO在FOO自己的实例初始化器中隐式引用来打破这个规则?这是如何编译的?它不仅可以编译,而且可以在运行时正常工作.
(在我看来,这mMap不是private因为我隐式创建了一个匿名子类,它不能引用private其超类中的字段.由于枚举是隐含的,因此本身有点奇怪final......)
如果枚举常量的构造函数、实例初始值设定项块或实例变量初始值设定项表达式引用
e或e声明在 右侧的相同类型的枚举常量,则会出现编译时错误e。
这里的规范只是意味着您不能按名称引用,因为 by 引用的字段e尚未初始化。这并不意味着您无法访问this.
它与任何其他初始化器的规则基本上相同(例如int x = x;。
我们可以通过一个例子来了解为什么(Ideone):
enum Example {
INSTANCE {{
subversion();
}};
static void subversion() {
System.out.println(INSTANCE);
}
public static void main(String[] args) {
System.out.println(INSTANCE);
}
}
Run Code Online (Sandbox Code Playgroud)
哪个输出
null
INSTANCE
Run Code Online (Sandbox Code Playgroud)
我发现如果
mMap是私有的,则无法在实例初始值设定项中引用它。
您可以将调用限定为super.mMap.put(...);。privatemMap不能被继承,但可以从内部类访问。我在这里也介绍了这一点。它的缺点是简单的名称mMap引用了一个不存在的外部实例Derp。
我们可以通过( Ideone )这样的例子来验证情况是否如此:
class Example {
private int x;
class Inner extends Example {{
x = 1; // refers to the outer instance
super.x = 2; // refers to the inner instance
}}
public static void main(String[] args) {
Example outer = new Example();
Example inner = outer.new Inner();
System.out.println(outer.x); // prints 1
System.out.println(inner.x); // prints 2
}
}
Run Code Online (Sandbox Code Playgroud)
除非你的情况FOO是静态的,所以没有外部实例 - 因此编译器错误。
| 归档时间: |
|
| 查看次数: |
281 次 |
| 最近记录: |