为什么enum的构造函数不能访问静态字段和方法?这对于类非常有效,但不允许使用枚举.
我要做的是将我的枚举实例存储在静态Map中.考虑这个允许通过abbreivation查找的示例代码:
public enum Day {
Sunday("Sun"), Monday("Mon"), Tuesday("Tue"), Wednesday("Wed"), Thursday("Thu"), Friday("Fri"), Saturday("Sat");
private final String abbreviation;
private static final Map<String, Day> ABBREV_MAP = new HashMap<String, Day>();
private Day(String abbreviation) {
this.abbreviation = abbreviation;
ABBREV_MAP.put(abbreviation, this); // Not valid
}
public String getAbbreviation() {
return abbreviation;
}
public static Day getByAbbreviation(String abbreviation) {
return ABBREV_MAP.get(abbreviation);
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为枚举不允许在其构造函数中使用静态引用.然而,如果实现为类,它只能找到:
public static final Day SUNDAY = new Day("Sunday", "Sun");
private Day(String name, String abbreviation) {
this.name = name;
this.abbreviation = abbreviation;
ABBREV_MAP.put(abbreviation, this); // Valid
}
Run Code Online (Sandbox Code Playgroud)
Jon*_*eet 109
在静态字段全部初始化之前调用构造函数,因为静态字段(包括表示枚举值的字段)按文本顺序初始化,并且枚举值始终位于其他字段之前.请注意,在您的类示例中,您没有显示ABBREV_MAP初始化的位置 - 如果它在 SUNDAY 之后,您将在初始化类时获得异常.
是的,这有点痛苦,可能设计得更好.
但是,根据我的经验,通常的答案是static {}
在所有静态初始化器的末尾都有一个块,并在那里进行所有静态初始化,EnumSet.allOf
用于获取所有值.
Pha*_*ani 30
引自JLS,"Enum Body Declarations"部分:
如果没有这个规则,由于枚举类型中固有的初始化循环性,显然合理的代码会在运行时失败.(具有"自键型"静态字段的任何类中都存在循环.)以下是失败的代码类型的示例:
Run Code Online (Sandbox Code Playgroud)enum Color { RED, GREEN, BLUE; static final Map<String,Color> colorMap = new HashMap<String,Color>(); Color() { colorMap.put(toString(), this); } }
此枚举类型的静态初始化将抛出NullPointerException,因为当枚举常量的构造函数运行时,静态变量colorMap未初始化.上述限制可确保此类代码无法编译.
请注意,可以轻松地重构该示例以使其正常工作:
Run Code Online (Sandbox Code Playgroud)enum Color { RED, GREEN, BLUE; static final Map<String,Color> colorMap = new HashMap<String,Color>(); static { for (Color c : Color.values()) colorMap.put(c.toString(), c); } }
重构版本显然是正确的,因为静态初始化从上到下发生.
小智 7
也许这就是你想要的
public enum Day {
Sunday("Sun"),
Monday("Mon"),
Tuesday("Tue"),
Wednesday("Wed"),
Thursday("Thu"),
Friday("Fri"),
Saturday("Sat");
private static final Map<String, Day> ELEMENTS;
static {
Map<String, Day> elements = new HashMap<String, Day>();
for (Day value : values()) {
elements.put(value.element(), value);
}
ELEMENTS = Collections.unmodifiableMap(elements);
}
private final String abbr;
Day(String abbr) {
this.abbr = abbr;
}
public String element() {
return this.abbr;
}
public static Day elementOf(String abbr) {
return ELEMENTS.get(abbr);
}
}
Run Code Online (Sandbox Code Playgroud)
通过嵌套类解决了这个问题.优点:CPU消耗更短,也更好.缺点:JVM内存中还有一个类.
enum Day {
private static final class Helper {
static Map<String,Day> ABBR_TO_ENUM = new HashMap<>();
}
Day(String abbr) {
this.abbr = abbr;
Helper.ABBR_TO_ENUM.put(abbr, this);
}
public static Day getByAbbreviation(String abbr) {
return Helper.ABBR_TO_ENUM.get(abbr);
}
Run Code Online (Sandbox Code Playgroud)