无法访问枚举初始化程序中的静态字段
在此代码中,我收到编译器错误,请参阅注释:
public enum Type {
CHANGESET("changeset"),
NEW_TICKET("newticket"),
TICKET_CHANGED("editedticket"),
CLOSED_TICKET("closedticket");
private static final Map<String, Type> tracNameMap = new HashMap<String, Type>();
private Type(String name) {
tracNameMap.put(name, this); // cannot refer to static field within an initializer
}
public static Type getByTracName(String tn) {
return tracNameMap.get(tracNameMap);
}
}
有没有办法使此工作正常,通过其字段之一从 Map
获取枚举值?
In this code I get a compiler error, see comment:
public enum Type {
CHANGESET("changeset"),
NEW_TICKET("newticket"),
TICKET_CHANGED("editedticket"),
CLOSED_TICKET("closedticket");
private static final Map<String, Type> tracNameMap = new HashMap<String, Type>();
private Type(String name) {
tracNameMap.put(name, this); // cannot refer to static field within an initializer
}
public static Type getByTracName(String tn) {
return tracNameMap.get(tracNameMap);
}
}
Is there a way to make this work, getting an enum value from a Map
by one of its fields?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
地图在这里可能有点过分了。除非您计划拥有四个以上的枚举值,否则您可以通过简单地迭代有效字符串并返回正确的字符串来实现 getByTracName(String tn) 。如果映射键始终是枚举名称,那么您可以执行以下操作:
}
或者您可以执行以下操作:
The map is probably overkill here. Unless you are planning on having many more than four enum values you can implement getByTracName(String tn) by simply iterating over the valid strings and returning the correct one. If the map keys are always the enum names then you can do:
}
or you can do:
哈,有趣!就在几天前,我偶然发现了这一点。
来自 Java 语言规范,第三版,第 8.9 节:
从构造函数引用不是编译时常量(第 15.28 节)的枚举类型的静态字段是一个编译时错误,实例初始值设定项块或该类型的实例变量初始值设定项表达式。如果枚举常量 e 的构造函数、实例初始值设定项块或实例变量初始值设定项表达式引用自身或声明在 e 右侧的相同类型的枚举常量,则会出现编译时错误。
讨论
如果没有这条规则,由于枚举类型固有的初始化循环性,显然合理的代码将在运行时失败。 (任何具有“自类型”静态字段的类中都存在循环性。)以下是会失败的代码示例:
此枚举类型的静态初始化将引发 NullPointerException,因为静态变量 colorMap 是当枚举常量的构造函数运行时未初始化。上述限制确保此类代码不会编译。
请注意,该示例可以轻松重构以正常工作:
重构版本显然是正确的,因为静态初始化是从上到下发生的。
Hah, funny! Just a few days ago, I stumbled across this.
From the Java Language Specification, Third Edition, Section 8.9:
It is a compile-time error to reference a static field of an enum type that is not a compile-time constant (§15.28) from constructors, instance initializer blocks, or instance variable initializer expressions of that type. It is a compile-time error for the constructors, instance initializer blocks, or instance variable initializer expressions of an enum constant e to refer to itself or to an enum constant of the same type that is declared to the right of e.
Discussion
Without this rule, apparently reasonable code would fail at run time due to the initialization circularity inherent in enum types. (A circularity exists in any class with a "self-typed" static field.) Here is an example of the sort of code that would fail:
Static initialization of this enum type would throw a NullPointerException because the static variable colorMap is uninitialized when the constructors for the enum constants run. The restriction above ensures that such code won't compile.
Note that the example can easily be refactored to work properly:
The refactored version is clearly correct, as static initialization occurs top to bottom.
我会使用 可逆枚举模式 :
ReversibleEnum.java
ReverseEnumMap.java
您可以按如下方式更改 Type.java:
I'd use the Reversible Enum Pattern:
ReversibleEnum.java
ReverseEnumMap.java
You'd change Type.java as follows:
这个怎么样?不需要您在两个地方进行代码更改,这在我看来很容易出错:
How about this; doesn't require you to make code changes at two places which is kind of error prone IMO:
我自己的解决方法,尽管它需要重复所有枚举值:
My own workaround, though it requires repeating all the enum values: