Static Initialization Before Enum Elements

It is not possible to make a static initialization before initialization of enum elements in Java since enum elements always have to be declared and initialized first.

If a static initialization doesn't depend on enum elements, its execution order after elements is not a problem. Otherwise, if an initialization depends on enum elements, this would cause trouble. However, Java enums provide values() method that is able to meet this dependency. But calling values() may be an overhead, because values() method copies the internal static array each time.

For example (edited in post Why can't enum's constructor access static fields?) :

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);
    }
}

As seen in the example, i wouldn't need static initialization code block, therefore calling values() method which makes a copy, if I were able to initialize HashMap before enum elements. The code commented out in the constructor would be sufficient.

My question is that, because obligation of initialization of enum elements first may end up with an unnecessary overhead, is it possible to eliminate this overhead or in other words is it possible to make static initialization before enum elements? If not is it just for the sake of code readibility? I assume that declaring enum elements first has nothing to do with safe initialization as mentioned in some answers.

In this question, I remark an overhead, even though most of the time it is small, at least it's worth for deep comprehension and maybe brainstorming.


As mental yoga (think what the compiler has to do):

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;
    }
}

Too perverse.


The answer above by Joop Eggen has inspired me of using static inner classes, even though it is an obvious workaround and a trick, it has showed me it is not impossible to eliminate this overhead and it is possible make static initializations before enum elements. It's been a good brainstorming.

My final code will be as follows for value table and constructor, static block will be removed and overhead will be eliminated:

//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);
}

This works, because static initialization occurs in first use of a class, an inner class in this case.

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

上一篇: 从String转换为具有大量值的Java枚举

下一篇: 枚举元素之前的静态初始化