我想定义一个枚举类型,其中两个常量的"值"相同.我将这两个常量称为重复.考虑以下示例:我想定义一个浏览器类型列表,我想要一个文字"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)
一种简单的方法是将实例变量放在枚举类中.
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)
在这种情况下,分层枚举技巧可能就是你想要的.虽然它没有解决比较问题,但它为您提供了一个非常好的替代方案.
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)
每个枚举相互扩展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)