Ming Xue Ming Xue - 7 months ago 18
Java Question

How can I define duplicate enumeration constants in Java?

I want to define an enum type with two constants whose "value" is the same. I call these two constants as duplicates. Consider the following example: I want to define a list of browser types, and I want to have both a literal "IE" and "InternetExplorer", as below:

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

String type;
Browser(String type) {
this.type = type;
}
}


However, with this, the following code will fail,

Browser a = Browser.IE;
Browser b = Browser.INTERNETEXPLORER;
Assert.assertTrue(a==b);


The only workaround I can think of is that to add a
value()
method of the
Browser
type that returns the internal value of the browser instance. And the equality test code would be

Assert.assertTrue(a.value()==b.value())


This is not nice. So does anyone have a better idea?

Why does Java not allow to override methods like
equals()
of
Enum<T>
class?

EDIT:

OK, thanks for the answers and comments. I agree that my original thought was against the purpose of enum. I think the following changes can meet my need.

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

Answer

Each enum mutually extends class Enum that defines equals() as final. This is done because enum is not a regular class. JVM guarantees that each enum element is unique, i.e. exists only one instance of each element within one JVM.

This is required for example for using enums in switch statement etc.

What you are trying to do is to go against this concept: you want to have 2 equal members of the same enum.

However I can offer you other solution: define only one IE member. Define String[] member into the enum and method that can find appropriate member by any alias:

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;
}
}