枚举元素之前的静态初始化



在Java中初始化枚举元素之前不可能进行静态初始化,因为枚举元素总是必须首先声明和初始化。

如果静态初始化不依赖于枚举元素,则其在元素之后的执行顺序不是问题。否则,如果初始化依赖于枚举元素,这将导致麻烦。但是,Java 枚举提供了能够满足此依赖关系的 values() 方法。但是调用 values() 可能是一种开销,因为 values() 方法每次都会复制内部静态数组。

例如(在帖子中编辑,为什么枚举的构造函数不能访问静态字段?

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>();
static
{
for(Day day:values())
ABBREV_MAP.put(day.abbreviation, day);
}
private Day(String abbreviation) {
this.abbreviation = abbreviation;
//ABBREV_MAP.put(abbreviation, this); this is not valid
}
public String getAbbreviation() {
return abbreviation;
}
public static Day getByAbbreviation(String abbreviation) {
return ABBREV_MAP.get(abbreviation);
}
}

如示例中所示,如果我能够在枚举元素之前初始化 HashMap,我将不需要静态初始化代码块,因此调用 values() 方法进行复制。在构造函数中注释掉的代码就足够了。

我的问题是,由于首先初始化枚举元素的义务最终可能会产生不必要的开销,是否有可能消除这种开销,或者换句话说,是否可以在枚举元素之前进行静态初始化?如果不是,仅仅是为了代码可读性吗?我假设首先声明枚举元素与某些答案中提到的安全初始化无关。

在这个问题中,我评论了一个开销,尽管大多数时候它很小,但至少值得深入理解,也许是头脑风暴。

作为心理瑜伽(想想编译器必须做什么):

public enum Day {
SUNDAY(A.Sun), MONDAY(A.Mon), TUESDAY(A.Tue),
WEDNESDAY(A.Wed), THURSDAY(A.Thu), FRIDAY(A.Fri), SATURDAY(A.Sat);
private enum A {
Sun(Day.SUNDAY), Mon(Day.MONDAY), Tue(Day.TUESDAY), Wed(Day.WEDNESDAY),
Thu(Day.THURSDAY), Fri(Day.FRIDAY), Sat(Day.SATURDAY);
private final Day day;
A(Day day) {
this.day = day;
}
}
private final A abbrev;
Day(A abbrev) {
this.abbrev = abbrev;
}
public static Day getByAbbreviation(String abbreviation) {
return A.valueOf(abbreviation).day;
}
}

太反常了。

Joop Eggen 上面的答案启发了我使用静态内部类,尽管这是一个明显的解决方法和技巧,但它向我表明消除这种开销并非不可能,并且可以在枚举元素之前进行静态初始化。这是一个很好的头脑风暴。

对于值表和构造函数,我的最终代码如下,静态块将被删除,开销将被消除:

//HashMap in inner class
public static class InnerMap
{
private static final Map<String, Day> ABBREV_MAP = new HashMap<String, Day>();
}
//Constructor
private Day(String abbreviation) {
this.abbreviation = abbreviation;
InnerMap.ABBREV_MAP.put(abbreviation, this);
}

这是有效的,因为静态初始化发生在第一次使用类时,在本例中是内部类。

最新更新