如何在Java中定义重复的枚举常量?

Min*_*Xue 10 java enums

我想定义一个枚举类型,其中两个常量的"值"相同.我将这两个常量称为重复.考虑以下示例:我想定义一个浏览器类型列表,我想要一个文字"IE"和"InternetExplorer",如下所示:

enum Browser {
    CHROME("chrome"),
    FIREFOX("firefox"),
    IE("ie"),
    INTERNETEXPLORER("ie");

    String type;
    Browser(String type) {
        this.type = type;
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,有了这个,以下代码将失败,

Browser a = Browser.IE;
Browser b = Browser.INTERNETEXPLORER;
Assert.assertTrue(a==b);
Run Code Online (Sandbox Code Playgroud)

我能想到的唯一解决方法是添加一个返回浏览器实例内部值value()Browser类型的方法.并且相等测试代码将是

Assert.assertTrue(a.value()==b.value())
Run Code Online (Sandbox Code Playgroud)

这不好.那么有没有人有更好的主意?

为什么Java不允许覆盖像类这样equals()的方法Enum<T>

编辑:

好的,谢谢你的回答和评论.我同意我原来的想法违背了枚举的目的.我认为以下变化可以满足我的需求.

public enum Browser {
   CHROME,
   FIREFOX,
   IE;

   public static Browser valueOfType(String type) {
       if (b == null) {
            throw new IllegalArgumentException("No browser of type " + type);
       switch (type.toLowerCase()) {   
          case "chrome":
               return Browser.CHROME;
          case "firefox":
               return Browser.FIREFOX;
          case "ie":
          case "internetexplorer":
          case "msie":
               return Browser.IE;
          default:
               throw new IllegalArgumentException("No browser of type " + type);
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

Xer*_*oOl 9

一种简单的方法是将实例变量放在枚举类中.

enum Browser {
    CHROME,
    FIREFOX,
    INTERNETEXPLORER;
    public static final Browser IE=INTERNETEXPLORER;
}
Run Code Online (Sandbox Code Playgroud)

然后,IE应该只是作为别名INTERNETEXPLORER,你可以互换使用它们.

编辑:感谢big_m建议制作IE final!

编辑2:这个技巧应该适用于大多数代码,但是如果你使用的话会有例外switch/case.这是一个例子:

Browser b;
switch(b){
    case Browser.CHROME:
        //code for chrome
        break;
    case Browser.IE: // <---- SYNTAX ERROR, use Browser.INTERNETEXPLORER in this case
        //code for internet explorer
        break;
}
Run Code Online (Sandbox Code Playgroud)

  • 好方案!不过,我会把它作为"静态决赛",因此无法改变. (2认同)

gig*_*dot 8

在这种情况下,分层枚举技巧可能就是你想要的.虽然它没有解决比较问题,但它为您提供了一个非常好的替代方案.

http://java.dzone.com/articles/enum-tricks-hierarchical-data

我直接引用上面网站的代码,略有简化:

public enum OsType {
    OS(null),
        Windows(OS),
            WindowsNT(Windows),
                WindowsNTWorkstation(WindowsNT),
                WindowsNTServer(WindowsNT),
            WindowsXp(Windows),
            WindowsVista(Windows),
            Windows7(Windows),
        Unix(OS),
            Linux(Unix),
    ;
    private OsType parent = null;

    private OsType(OsType parent) {
        this.parent = parent;
    }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*exR 7

每个枚举相互扩展Enum定义equals()为的类final.这样做是因为枚举不是常规类.JVM保证每个枚举元素都是唯一的,即在一个JVM中只存在每个元素的一个实例.

这是例如在switch语句等中使用枚举所必需的.

你要做的就是违背这个概念:你想拥有相同枚举的2个相等的成员.

但是,我可以为您提供其他解决方案:仅定义一个IE成员.将String[]成员定义到枚举和方法中,可以通过任何别名找到适当的成员:

public enum Browser {


    CHROME("Chrome"),
    FIREFOX("FireFox"),
    IE("IE", "MSIE", "Microsoft Internet Exporer"),
    ;

    private String[] aliases;

    private static Map<String, Browser> browsers = new HashMap<>();
    static {
        for (Browser b : Browser.values()) {
            for (String alias : b.aliases) {
                browsers.put(alias, b);
            }
        }
    }

    private Browser(String ... aliases) {
        this.aliases = aliases;
    }

    public static Browser valueOfByAlias(String alias) {
        Browser b = browsers.get(alias);
        if (b == null) {
            throw new IllegalArgumentException(
                    "No enum alias " + Browser.class.getCanonicalName() + "." + alias);
        }
        return b;
    }
}
Run Code Online (Sandbox Code Playgroud)