oak oak - 1 year ago 76
Java Question

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 http://stackoverflow.com/questions/443980/why-cant-enums-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.

oak oak
Answer Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download