How to define duplicate enumeration constants in Java?

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

enum Browser { CHROME("chrome"), FIREFOX("firefox"), IE("ie"), INTERNETEXPLORER("ie"); String type; Browser(String type) { this.type = type; } } 

However, the following code will not be executed,

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

The only workaround I can come up with is to add a value() method of type Browser that returns the internal value of the browser instance. And the equality verification code will be

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

It is unpleasant. So does anyone have a better idea?

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

EDIT

Ok, thanks for the answers and comments. I agree that my original thought was directed against the purpose of the listing. I think the following changes may satisfy 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); } } } 
+7
source share
7 answers

Each enumeration mutually extends the Enum class, which defines equals() as final . This is because the enumeration is not an ordinary class. The JVM ensures that each element of the enumeration is unique, i.e. There is only one instance of each item in one JVM.

This is necessary, for example, to use enumerations in a switch , etc.

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

However, I can offer you another solution: define only one IE member. Define the String[] member in the enumeration and method that the corresponding member can find 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; } } 
+6
source

One easy way to do this is to put instance variables inside your enum class.

 enum Browser { CHROME, FIREFOX, INTERNETEXPLORER; public static final Browser IE=INTERNETEXPLORER; } 

Then, IE should just act as an INTERNETEXPLORER alias, and you can use them interchangeably.

EDIT: thanks big_m for making IE final !

EDIT2: This trick should work in most codes, but there is an exception if you use switch/case . Here is an example:

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

A hierarchical approach to enumeration is probably what you want in this case. Although this does not solve the problem of comparison, it provides a very nice alternative to your problem.

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

I quote the codes from the site directly with a slight simplification:

 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; } } 
+5
source

You cannot override the equals() method to enumerate, but even if the == operator did not execute the equals() method: there is no way to make a == b be true for your example.

The closest I can think of is a utility method (static):

 enum Browser { CHROME("chrome"), FIREFOX("firefox"), IE("ie"), INTERNETEXPLORER("ie"); private final String type; Browser(String type) { this.type = type; } public String getType() { return type; } public static boolean equals(Browser b1, Browser b2) { return b1.type.equals(b2.type); } } 

Also note that I would do type private final . Be that as it may, you can do this:

 IE.type = "netscape"; // would be allowed 
+1
source

What you really have to do is normalize the conversion of input to enum, i.e. if your input (from a user / data store) is IE / INTERNETEXPLORER, it must be enabled by Browser.IE. This will remove a lot of redundant checks in the code to find out if the enum is IE or INTERNETEXPLORER.

0
source

As written in Enum Class

but the extension of this class does not make the class an enumeration type, since the compiler must generate special information for it.

To support equality based on the reference method, equals is final.

You can use EnumSet to create EnumSet Related Enumerations, and then you can use the contains method.

 public static EnumSet<Browser> MSE = EnumSet.of(Browser.IE, Browser.INTERNETEXPLORER); 

So your code will look something like this.

 public enum Browser { CHROME("chrome"), FIREFOX("firefox"), IE("ie"), INTERNETEXPLORER("ie"); String type; Browser(String type) { this.type = type; } public static EnumSet<Browser> MSE = EnumSet.of(Browser.IE, Browser.INTERNETEXPLORER); public static void main(String[] args) { System.out.println(MSE.contains(Browser.IE));//true System.out.println(MSE.contains(Browser.INTERNETEXPLORER));//true } } 
0
source

I would delete the string value and duplicate instance of IE, not to use it ...

 enum Browser { CHROME, FIREFOX, IE 

If you should have a lowercase representation, just convert from an enumeration name when you need it.

-2
source

All Articles