1

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.

Community
  • 1
  • 1
oak
  • 199
  • 1
  • 6
  • 2
    This "overhead" is only a few **micro**seconds (probably less) and will only be run once in your program. I'm sure there are better candidates for performance tuning in your code. – assylias May 12 '17 at 13:50
  • I mean why not is it just perfect as expected from a great programming language even though it is so straightforward? Or is it just for code readibility? – oak May 12 '17 at 13:53
  • Check out the [answers in this question](http://stackoverflow.com/q/443980/135078) as they seem to be providing more detail, just not sure if it's enough for your question, which is why I'm voting to reopen. – Kelly S. French May 12 '17 at 15:36

2 Answers2

2

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.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • If built-in valueOf method uses a HashMap internally, that will cancel out the overhead. But not, it may cost more than HashMap when accessing elements. However, you gave me the idea that we could use normal inner classes like this way and implement a HashMap inside it. I was thinking it was impossible to eliminate this overhead. Inner static classes become workarounds for static initialization. Thanks for your brainstorming! – oak May 22 '17 at 15:24
  • I made changes to the code. Please check out my answer! – oak May 22 '17 at 15:41
  • In fact trimming the enum to three letters already would have done it. ;) – Joop Eggen May 22 '17 at 18:25
  • But the life is not always so :) – oak May 22 '17 at 18:58
1

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.

oak
  • 199
  • 1
  • 6