Java Enums

In the comments to my last post I saw that java enums as they are implemented now find very little appreciation with non-java programmers. Java enums differ vastly from enums in C/++. I believe this has “historical” reasons.

As C/++ programmers have noted before, java programmers will be whining until every remotely useful feature of C/++ will also be available in java and they still think that java is so much better. Right? So there were no enums in java (until jdk 1.5, wait it’s 5.0) and java programmers not only whined but they got creative and developed their own pattern to emulate enums: the typesafe enum pattern. As opposed to C/++ java is (supposed to be, but only if you do it right!) typesafe and therefore java programmers not only wanted enums but typesafe enums. Here’s the example:

//The typesafe enum pattern
public class Suit {
    private final String name;

    public static final Suit CLUBS =new Suit("clubs");
    public static final Suit DIAMONDS =new Suit("diamonds");
    public static final Suit HEARTS =new Suit("hearts");
    public static final Suit SPADES =new Suit("spades");  
  
    private Suit(String name){         this.name =name;    }
    public String toString(){        return name;    }
}

Once they had realised they could emulate enums this way, the pattern was refined into different directions. Using anonymous classes for example you could attach different behaviour to the constants. This pattern is described in detail in Effective Java and in the java language guide: enums. The language guide is for java 5.0. Here’s the sample from the guide that I am emulating:

public enum Operation {
  PLUS   { double eval(double x, double y) { return x + y; } },
  MINUS  { double eval(double x, double y) { return x - y; } },
  TIMES  { double eval(double x, double y) { return x * y; } },
  DIVIDE { double eval(double x, double y) { return x / y; } };

  // Do arithmetic op represented by this constant
  abstract double eval(double x, double y);
}

I think it is pretty neat and once you have understood this and the use of anonymous classes, it is a pretty tasty idiom.

By the way: Effectively the enum example above is the “replace switch with polymorphism” refactoring mentionned in the comments.

As to the argument that this is bad for readbility? The first time I saw someone lazy-initializing a singleton (yes with the faulty double-checking) I didn’t get it and now it’s just as much as “not that one again!” Most code isn’t easy to read for beginners but this sure isn’t obfuscated enough to secure your job!

Fazit: I think that java enums have an entirely different history and demands to satisfy than enums in C/++. C/++ has simple constants while java allows for very powerful, obfuscated and (yes!) faulty constructs. And when it is possible to have constant specific methods with the original typesafe enum pattern nobody would want to miss those in a java enum implementation.

7 Replies to “Java Enums”

  1. Of course you could well make the point that while the typesafe enum pattern is now part of the language spec, Java *still* has no way of having enums of primitive value types. Since enums are always objects, they carry all the overhead associated with that. In other languages an enum is, to the compiler, just a number. Plus you can still use that typesafe enum pattern in other languages, if you wish to do so.

    As far as obfuscation goes: It is a code smell. Code is a special kind of prose, which is always hard to read. One should not make it any harder without a good reason.

  2. So in fact, the main difference between C++ and Java is that in C++, enums are self defined “basic” (or value) types, and in Java, they are Objects. Since in Java there are no self defined value types, it would be inconsistent to introduce such a concept.
    It seems to me, as though enum in C++ in quite something different as an enum in Java.
    The question still to discuss might be: Do I need the additional features that Java-Enums offer the programmer? How often do you benefit from the simplicity of the enum? Is it really worth a new language feature?

  3. @Daniel:
    Obfuscation may be code smell but I didn’t quite mean to say what I obviously said. I do not think it is obfuscated, I wanted to suggest that some may think it is obfuscation. My example of the lazy initialization double checking pattern was supposed to illustrate that (despite the specific example being faulty) with sufficient exposure to a pattern or idiom it becomes self-evident. In my opinion once one has understood it and it is used in a fitting environment (as opposed to “overused”) it can be way more elegant and simple than other implementations using polymorphism et al.

    I just have to requote the sentence about constant specific methods that I linked to above: “Constant-specific methods are reasonably sophisticated, and many programmers will never need to use them, but it is nice to know that they are there if you need them.”

    From a previous discussion with Rolland I know that it really takes time to get used to this. After an hour of explanations I had him nearly convinced. Except he still thinks that a “switch” is the best way to implement a finite state machine. I submitted my state machine to Micha for a review but never heard of him again. So either my code is so awful he didn’t want to embarrass me or he just forgot.

  4. @Uli “King of Boredom”
    Very different indeed.

    Is it necessary? I am not sure about that myself. I read about the “constant specific methods”, “typesafe enums” and the rest before I started using java 5. When I saw that the older patterns and idioms were simply replaced with s/class/enum/g, I was wondering why enums were really needed.

    You can use enums in a very simple way:

     .... enum Color { RED,BLUE,YELLOW } ...

    That’s it. Can be used whereever classes are allowed. It has a couple of advantages if not many. For example the string output of a Color will be the name of the Color. No further evil constructs necessary. It’s just that these things are references. I can live with that, don’t you argue performance because that is not my first concern. If it is an issue I can still refactor the enum back to some class with constants during optimization stage.

    The simple way was there first, but I don’t think anyone would have had enums had they not also supported the “constant specific methods” because that’s what many people are already using. But I am not part of the JCP so I have really no idea what I am talking about except: I am using enums for now with the simple version because if I really need “constant specific methods” I’ll be using it with classes which are much more versatile.

    Ask me again in a few months and I might have another opinion.

  5. I agree on the fact that en anum of type
    enum Color { RED, BLUE, YELLOW }
    is somehting that is really useful. I as well think that this is a necessary feature. The question I asked was: Is it necessary to bundel methods to this enums? In C++, it definitely does not make sense, cause you expect performance from a value type. As well operator overloading enables you to overcome some of the cases, where having methods on an enum is useful. In Java, enums are object – which is a consistent solution in the java context. So having methods on it is, let’s say, consequent. Nevertheless, I am not sure whether it would be better in most cases to restrict yourself and not use them.

    I mean, in C++, I can write
    while (*d++ = *s++);
    to copy a string. But do I have to? (Thank’s to Joel for the example….)

    Anyway… 😉

  6. As I said, I think the “methods” in the enums are historically grown and since many java fans aren’t primarily thinking in performance gains my guess simply is that they wanted the language feature and they wanted to use in the same way that the workaround evolved.

    Just a guess.

    Obfuscation rules!

  7. Wenn ihr mit diesen Enums (die ich übrigens ziemlich schick finde) C/C++-switches ersetzen wollt, dann braucht ihr doch diese Methoden.Was in den Methoden steht ist doch genau das, was bei C zwischen case und break steht. Und wenn Du alle Methoden in der Klasse hintereinander stehen hast, dann unterscheidet sich das optisch kaum noch von einem C-switch:

    public enum Operation {
    PLUS { double eval(double x, double y) { return x + y; } },
    MINUS { double eval(double x, double y) { return x – y; } },

    }

    vs.

    double eval(operation_t operation, double x, double y) {
    switch(operation) {
    case PLUS: return x+y; break;
    case MINUS: return x-y; break;

    }
    }

    Was ich dann allerdings nicht verstehe ist, wo Ulis Argument der besseren Lesbarkeit gegenüber “ellenlangen” Switch-Statements bleibt. Gleich eingesetzt sieht das beides verdammt gleich aus, es gibt sogar Aspekte, die ich in diesem Beispiel bei der C-Version lesbarer finde (dass da nur einmal eval() steht z.b.)

    Man hat halt den Vorteil, dass man sich nicht wie bei C noch in irgendeiner Header-Datei mit einem Haufen #defines oder dem eigentlich typedef enum … rumschlägt, aber das ist ja bei Java immer so und keine spezielle Eigenschaft der Java-Enums.

Comments are closed.