What are some advantages of making enum in Java similar to a class, rather than just a collection of constants as in C/C++?
Enums are already a class in Java.
If you're asking why this is better, I'd say that better type safety and the ability to add other attributes besides a mere ordinal value would come to mind.
Enums are a type in itself - you cannot use an enum that does not exist, or put in some other similar looking constant. and also, you can enumerate them, so that code can be more concise.
using static constants could potentially cause maintenence nightmares - especially if they area spread out.
You get free compile time checking of valid values. Using
public static int OPTION_ONE = 0;
public static int OPTION_TWO = 1;
does not ensure
void selectOption(int option) {
...
}
will only accept 0 or 1 as a parameter value. Using an enum, that is guaranteed. Moreover, this leads to more self documenting code, because you can use code completion to see all enum values.
Type safety is one reason.
Another, that I find more important, is that you can attach metadata to enum values in Java. For example, you could use an enum to define the set of legal operations for a webservice, and then attach metadata for the type of request and data class:
AddItem(HttpMethod.POST, ProductEntry.class),
In addition to better type safety, you can also define custom behavior in your enums (refer to Effective Java for some good examples).
Making enum a reference type that can contain fixed set of constants has led to efficient Map implementation like EnumMap and Set implementation like EnumSet (JDK classes).
From javadoc of EnumMap :
A specialized Map implementation for use with enum type keys. All of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. Enum maps are represented internally as arrays. This representation is extremely compact and efficient.
EnumMap combines richness and type safety of Map with the speed of an array (Effective Java).
The only real advantage is that it can be used in a switch
statement. All the other stuff an enum is capable of can just be done with plain vanilla class with a private
constructor whose instances in turn are declared as public static final
fields of the class in question (the typesafe pattern). The other advantage of enum is obviously that it makes the code less verbose than you would do with a plain vanilla class.
But if I'm not mistaken, in C++ (or was it C#?) you can use a String
in a switch
statement. So that advantage of enums in Java is negligible as opposed to C++. However, same thing was proposed for Java 7, not sure if it will make it.
Java 5 enums originated from a typesafe enum pattern from Joshua Bloch's Effective Java (the first edition) to avoid the pitfalls of enums in C/C++/C# (which are simply thinly-veiled int constants) and the use in Java of final static int constants.
Primarily int constants and int enums aren't typesafe. You can pass in any int value. In C/C++ you can do this:
enum A { one, two, three };
enum B { beef, chicken, pork } b = beef;
void func(A a) { ... }
func((A)b);
Unfortunately the typesafe enum pattern from Effective Java had a lot of boilerplate, not all of it obvious. The most notable is you had to override the private method readResolve
to stop Java creating new instances on deserialization, which would break simple reference checking (ie using the ==
operator instead of equals()
).
So Java 5 enums offer these advantages over ints:
- Type safety;
- Java 5 enums can have behaviour and implement interfaces;
- Java 5 enums have some extremely lightweight data structures like
EnumSet
andEnumMap
.
Java 5 enums over these advantages over just using classes:
- Less error-prone boilerplate (private constructor,
readResolve()
etc); - Semantic correctness. You see something is an enum and you know it's just representing a value. You see a class and you're not sure. Maybe there's a static factory method somewhere, etc. Java 5 enums much more clearly indicate intent.
You can use enums to effectively implement Singletons ^^:
public enum Elvis {
INSTANCE
}