views:

1245

answers:

6

In Java, an Enum can do the great things that Enums do, but can also have methods (behavior and logic). What advantage does that have over using a class using an enum? Simple examples to illustrate the point would also be welcome.

+5  A: 

I'm not quite sure where the title of the question fits in with the rest of it. Yes, Java enums have behaviour. They can have state too, although it should really, really be immutable state. (The idea of a mutable enum value is pretty scary IMO.)

An enum in Java is a fixed set of objects, basically. The benefit is that you know that if you have a reference of that type, it's always either null or one of the well-known set.

Personally I really love Java enums and wish C# had them too - they're much more object-oriented than C#'s enums which are basically "named numbers". There are a few "gotchas" in terms of initialization order, but they're generally fab.

Jon Skeet
Can't you emulate Java enums with C# classes?
Vilx-
@Vilx: Of course you can. Before Java 5, you could write your own classes to make typesafe enum objects. (Well, you still can, of course, there's just not much of a point.)
Eddie
Vilx: You can, but it's a bit nasty. Basically you use an abstract base type with a private constructor, and derive from it with *nested* types which can call the private constructor.
Jon Skeet
I'd like to add a few more really's to "really, really be immutable state"
Scott Stanchfield
Can you give me a quick example of an enum with a state? Just trying to wrap my brain around that.
Dopyiii
One example might be card suits, where each suit could have a name and an image associated with it.
Jon Skeet
+1  A: 

In our project, we're using Enums for a few things, but perhaps most prominently for i18n purposes - each piece of shown text is given an Enum. The Enum class has a String-returning method that inspects the Locale that is being used, and picks the correct translation from a collection of translations on runtime.

This serves as a dual-purpose - you get code completion from your IDE, and also never forget to translate a string.

The usage is very simple, to the point that it's almost rendundant to give an example, but here's how one might use the translation-enum

System.out.println(Translations.GREET_PERSON.trans()+" "+user.getName());

Or, if you want to be fancy, have the Enum accept arguments, which will, with some magic string manipulation, be inserted in a marked position in the translations string

System.out.println(Translations.GREET_PERSON.trans(user.getName());
Henrik Paul
Interesting usage, but it would seem like you could get the same behavior from a series of static methods in a class. Guess I don't see the advantage of using the enum.
Dopyiii
Enums are much easier to add when needed. They are self aware too - you can get the string of the enum itself within trans() - therefore, you can use that as a keyword to match against in your translations-table
Henrik Paul
+10  A: 

Here's a simple example:

enum RoundingMode {
 UP {
  public double round(double d) {
   return Math.ceil(d);
  }
 },
 DOWN {
  public double round(double d) {
   return Math.floor(d);
  }
 };

 public abstract double round(double d);
}
Adam Crume
How would you use this in code? Do I just do this? double foo = RoundingMode.round(20.3);Or would you extend the enum to child enum? I'm thrown off by the abstract method.
Dopyiii
The abstract method is overridden by the nested classes used by UP and DOWN. You'd use it in code like this: double doMath(RoundMode m, double x, double y) { double d; ... d = m.round(d); ... return d; } You'd pass in RoundingMode.UP or RoundingMode.DOWN as the first parameter.
Adam Crume
Thanks! Not sure how I feel about that, but I understand it now ;)
Dopyiii
+6  A: 

Enum types are also a great way to implement true singletons.

Classic singleton patterns in Java typically involve private constructors and public static factory methods but are still vulnerable to instantiation via reflection or (de-)serialization. An enum type guards against that.

Steve Reed
Although you do get some odd method "for free". (Anyway singletons are evil.)
Tom Hawtin - tackline
I don't understand the comment.
Steve Reed
Interesting point. How does the enum guard against reflection and deserialization? I guess I'm asking, what actually prevents me from instantiating an enum via reflection? Does the compiler throw a checked exception?
Dopyiii
If you load an enum class and get an instance via reflection it will work, you will just get the same exact instance as you would normally.
Steve Reed
+2  A: 

Because the enum instances are singletons, you can use them in switch statements or with == to check equality.

Jason S
+1  A: 

Basically, Java enums are classes (I don't believe there is a difference at the bytecode level), with the additional benefit of having a known fixed set of possible instances and being able to use them in switch statements.

You can emulate the "known fixed set of possible instances" with regular classes (the "typesafe enum" pattern described in countless books and articles), but it's quite some work (repeated for every such class) to get it to work really correctly in regard to Serialization, equals() and hashCode(), and perhaps some other things I forgot. Language-level enums spare you that work. And, as mentioned above, only language-level enums can be used in switch statements.

Michael Borgwardt
They are classes, but there is a difference at the bytecode level. For one thing, enum classes have the ACC_ENUM flag. See http://java.sun.com/docs/books/jvms/second_edition/ClassFileFormat-Java5.pdf.
Adam Crume