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

在初始化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);
}

这是有效的,因为静态初始化在第一次使用类时发生,在这种情况下是内部类。

链接地址: http://www.djcxy.com/p/38079.html

上一篇: Static Initialization Before Enum Elements

下一篇: Private enums and static fields in the enclosing class