- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我想创建一个 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<>();
}
我发现如果mMap
是private
,它就不能在实例初始化器中被引用。错误是 Cannot make a static reference to the non-static field mMap
。在我想到这个原因之前,我咨询了JLS §8.9.2 ,部分内容是:
It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant
e
to refer toe
or to an enum constant of the same type that is declared to the right ofe
.
我在 FOO
自己的实例初始化器中隐式引用 FOO
不是违反了这个规则吗?这是如何编译的?它不仅可以编译,而且可以在运行时正常工作。
(我想到 mMap
不能是 private
因为我隐式创建了一个匿名子类,它不能引用 private
字段它的父类(super class)。这本身有点奇怪,因为枚举隐式地 final
...)
最佳答案
It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant
e
to refer toe
or to an enum constant of the same type that is declared to the right ofe
.
这里的规范只是意味着你不能通过name 来引用,因为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);
}
}
哪些输出
null
INSTANCE
I found that if
mMap
is private, it cannot be referenced in the instance initializer.
您可以将调用限定为 super.mMap.put(...);
。私有(private) mMap
不是继承的,但可以从内部类访问。 I also covered this here .简而言之,简单名称 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
}
}
除了你的情况 FOO
是静态的,所以没有外部实例——因此编译器错误。
关于java - 为什么这个枚举编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29641012/
我是一名优秀的程序员,十分优秀!