无法访问枚举初始化程序中的静态字段

Bar*_*lom 2 java enums static initializer

在这段代码中我得到一个编译器错误,请参阅注释:

 public enum Type {
   CHANGESET("changeset"),
   NEW_TICKET("newticket"),
   TICKET_CHANGED("editedticket"),
   CLOSED_TICKET("closedticket");

   private static final Map<String, Type> tracNameMap = new HashMap<String, Type>();

   private Type(String name) {
    tracNameMap.put(name, this); // cannot refer to static field within an initializer
   }

   public static Type getByTracName(String tn) {
    return tracNameMap.get(tracNameMap);
   }

  }
Run Code Online (Sandbox Code Playgroud)

有没有办法让这个工作,从Map其中一个字段获取枚举值?

DJC*_*rth 9

这张地图可能有点过头了.除非您计划使用多于四个枚举值,否则只需迭代有效字符串并返回正确的字符串即可实现getByTracName(String tn).如果地图键始终是枚举名称,那么您可以执行以下操作:

public enum Type {
CHANGESET,
NEW_TICKET,
TICKET_CHANGED,
CLOSED_TICKET;

private static final Map<String, Type> tracNameMap = new HashMap<String, Type>();
static {
    for (Type t:Type.values()) {
        tracNameMap.put(t.name(), t);
    }
}
public static Type getByTracName(String tn) {
    return tracNameMap.get(tracNameMap);
}
Run Code Online (Sandbox Code Playgroud)

}

或者你可以这样做:

public static Type getByTracName(String tn) {
  return Enum.valueOf(Type.class,tn);
}
Run Code Online (Sandbox Code Playgroud)


T-B*_*ull 7

哈,好笑!就在几天前,我偶然发现了这一点.

从Java语言规范,第三版,第8.9节:

从构造函数,实例初始化程序块或该类型的实例变量初始化程序表达式引用枚举类型的静态字段(不是编译时常量(第15.28节))是编译时错误.对于构造函数,实例初始化程序块或枚举常量e的实例变量初始化程序表达式来说,它是一个编译时错误,用于引用它自身或引用到e右侧的相同类型的枚举常量.

讨论

如果没有这个规则,由于枚举类型中固有的初始化循环性,显然合理的代码会在运行时失败.(具有"自键型"静态字段的任何类中都存在循环.)以下是失败的代码类型的示例:

enum Color {
        RED, GREEN, BLUE;
        static final Map<String,Color> colorMap = 
        new HashMap<String,Color>();
        Color() {
            colorMap.put(toString(), this);
        }
    } 
Run Code Online (Sandbox Code Playgroud)

此枚举类型的静态初始化将抛出NullPointerException,因为当枚举常量的构造函数运行时,静态变量colorMap未初始化.上述限制可确保此类代码无法编译.

请注意,可以轻松地重构该示例以使其正常工作:

enum Color {
        RED, GREEN, BLUE;
        static final Map<String,Color> colorMap = 
        new HashMap<String,Color>();
        static {
            for (Color c : Color.values())
                colorMap.put(c.toString(), c);
        }
    } 
Run Code Online (Sandbox Code Playgroud)

重构版本显然是正确的,因为静态初始化从上到下发生.