14

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.

Dave
  • 3,919
  • 5
  • 28
  • 34

7 Answers7

18

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
  • 14,820
  • 6
  • 44
  • 50
  • 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. – Dave Apr 08 '09 at 05:32
  • 1
    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 Apr 08 '09 at 14:04
  • Thanks! Not sure how I feel about that, but I understand it now ;) – Dave Apr 08 '09 at 14:30
9

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
  • 2,385
  • 2
  • 19
  • 20
  • Although you do get some odd method "for free". (Anyway singletons are evil.) – Tom Hawtin - tackline Apr 07 '09 at 23:28
  • I don't understand the comment. – Steve Reed Apr 08 '09 at 01:11
  • 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? – Dave Apr 08 '09 at 05:25
  • 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 Apr 08 '09 at 13:51
7

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
  • 1,261,211
  • 792
  • 8,724
  • 8,929
  • Can't you emulate Java enums with C# classes? – Vilx- Apr 07 '09 at 14:57
  • @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 Apr 07 '09 at 15:03
  • 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 Apr 07 '09 at 15:34
  • I'd like to add a few more really's to "really, really be immutable state" – Scott Stanchfield Apr 07 '09 at 17:58
  • Can you give me a quick example of an enum with a state? Just trying to wrap my brain around that. – Dave Apr 08 '09 at 05:29
  • One example might be card suits, where each suit could have a name and an image associated with it. – Jon Skeet Apr 08 '09 at 06:21
2

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

Jason S
  • 171,795
  • 155
  • 551
  • 900
2

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
  • 327,225
  • 74
  • 458
  • 699
  • 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 Apr 07 '09 at 18:48
1

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
  • 63,711
  • 30
  • 82
  • 93
  • 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. – Dave Apr 08 '09 at 05:21
  • 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 Apr 08 '09 at 06:49
0

Take a look at java/joda time classes, where enums do hell of a lot of job.

Here is an example of java.time.Month:

public enum Month implements TemporalAccessor, TemporalAdjuster {
    JANUARY,
    FEBRUARY,
    MARCH,
    APRIL,
    MAY,
    JUNE,
    JULY,
    AUGUST,
    SEPTEMBER,
    OCTOBER,
    NOVEMBER,
    DECEMBER;

    private static final Month[] ENUMS = Month.values();

    public static Month of(int month) {
        if (month < 1 || month > 12) {
            throw new DateTimeException("Invalid value for MonthOfYear: " + month);
        }
        return ENUMS[month - 1];
    }

    // About a dozen of other useful methods go here 

}
Nestor Milyaev
  • 3,655
  • 1
  • 25
  • 38