为什么枚举的构造函数不能访问静态字段?

为什么枚举的构造函数不能访问静态字段和方法?这对于一个类是完全有效的,但对于枚举是不允许的。


我正在尝试将枚举实例存储在静态Map中。考虑下面的示例代码,它允许通过abbreivation查找:


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


    private Day(String abbreviation) {

        this.abbreviation = abbreviation;

        ABBREV_MAP.put(abbreviation, this);  // Not valid

    }


    public String getAbbreviation() {

        return abbreviation;

    }


    public static Day getByAbbreviation(String abbreviation) {

        return ABBREV_MAP.get(abbreviation);

    }

}

这将不起作用,因为枚举不允许在其构造函数中使用静态引用。但是,它只是在实现为类的情况下才起作用:


public static final Day SUNDAY = new Day("Sunday", "Sun");

private Day(String name, String abbreviation) {

    this.name = name;

    this.abbreviation = abbreviation;

    ABBREV_MAP.put(abbreviation, this);  // Valid

}


慕无忌1623718
浏览 652回答 3
3回答

人到中年有点甜

因为所有静态字段(包括表示枚举值的静态字段)都是按文本顺序初始化的,而枚举值始终位于其他字段之前,所以在初始化静态字段之前会调用构造函数。请注意,在您的类示例中,您没有显示ABBREV_MAP的初始化位置-如果在&nbsp;SUNDAY&nbsp;之后,则在初始化类时会出现异常。是的,这有点痛苦,可能设计得更好。但是,根据我的经验,通常的答案是static {}在所有静态初始化程序的末尾添加一个块,然后在其中进行所有静态初始化,EnumSet.allOf&nbsp;以获取所有值。

呼啦一阵风

引用JLS,“枚举主体声明”部分:没有此规则,由于枚举类型固有的初始化循环性,显然合理的代码将在运行时失败。(在具有“自类型”静态字段的任何类中都存在圆度。)这是将失败的那种代码的示例:enum Color {&nbsp; &nbsp; RED, GREEN, BLUE;&nbsp; &nbsp; static final Map<String,Color> colorMap = new HashMap<String,Color>();&nbsp; &nbsp; Color() {&nbsp; &nbsp; &nbsp; &nbsp;colorMap.put(toString(), this);&nbsp; &nbsp; }}此枚举类型的静态初始化将引发NullPointerException,因为在运行枚举常量的构造函数时,静态变量colorMap未初始化。上面的限制确保了此类代码不会编译。请注意,可以轻松地将示例重构为正常工作:enum Color {&nbsp; &nbsp; RED, GREEN, BLUE;&nbsp; &nbsp; static final Map<String,Color> colorMap = new HashMap<String,Color>();&nbsp; &nbsp; static {&nbsp; &nbsp; &nbsp; &nbsp; for (Color c : Color.values())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; colorMap.put(c.toString(), c);&nbsp; &nbsp; }}重构版本显然是正确的,因为静态初始化是自上而下进行的。

慕桂英3389331

也许这就是你想要的public enum Day {&nbsp; &nbsp; Sunday("Sun"),&nbsp;&nbsp; &nbsp; Monday("Mon"),&nbsp;&nbsp; &nbsp; Tuesday("Tue"),&nbsp;&nbsp; &nbsp; Wednesday("Wed"),&nbsp;&nbsp; &nbsp; Thursday("Thu"),&nbsp;&nbsp; &nbsp; Friday("Fri"),&nbsp;&nbsp; &nbsp; Saturday("Sat");&nbsp; &nbsp; private static final Map<String, Day> ELEMENTS;&nbsp; &nbsp; static {&nbsp; &nbsp; &nbsp; &nbsp; Map<String, Day> elements = new HashMap<String, Day>();&nbsp; &nbsp; &nbsp; &nbsp; for (Day value : values()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elements.put(value.element(), value);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; ELEMENTS = Collections.unmodifiableMap(elements);&nbsp; &nbsp; }&nbsp; &nbsp; private final String abbr;&nbsp; &nbsp; Day(String abbr) {&nbsp; &nbsp; &nbsp; &nbsp; this.abbr = abbr;&nbsp; &nbsp; }&nbsp; &nbsp; public String element() {&nbsp; &nbsp; &nbsp; &nbsp; return this.abbr;&nbsp; &nbsp; }&nbsp; &nbsp; public static Day elementOf(String abbr) {&nbsp; &nbsp; &nbsp; &nbsp; return ELEMENTS.get(abbr);&nbsp; &nbsp; }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java