Java Enums

Two interesting insights about Java enums that I found today that are not obvious and might be useful for others.

Enums with methods

Sometimes it can be useful to associate certain behaviour to an enum constant. For example, today I wrote an enum that represents the different types of images of the X protocol:

public enum Format {
  BITMAP, XYPIXMAP, ZPIXMAP
}

Later in the protocol implementation I needed the IDs that are associated with each format. My first implementation used a switch statement (see below) to determine the ID. However, there’s a more elegant way to implement this:

public static enum Format {

  BITMAP   { public int id() { return 0; } },
  XYPIXMAP { public int id() { return 1; } },
  ZPIXMAP  { public int id() { return 2; } };

  public abstract int id ();

}

Ok, you can say that I could have used the ordinal() method of the enum. However, the above is more powerful. You can implement arbitrarily complex methods (with parameters etc) in an enum. I would tend to be concise though, and not implement anything that doesn’t fit on one or two lines.

Enums in switch statements

Well, this is of course a central design aspect of enums. I found it a little difficult though, until I found the correct syntax. What I did is that:

switch (format) {

  case Image.Format.BITMAP: // blah
  case Image.Format.XYPIXMAP: // blah
  case Image.Format.ZPIXMAP // blah

}

Looks like an obvious approach right? Well the compiler didn’t like it. It took me a while and some hints by friends on IRC to find out what’s correct:

switch (format) {

  case BITMAP: // blah
  case XYPIXMAP: // blah
  case ZPIXMAP: // blah

}

The case labels ‘inherit’ the type from the object passed into the switch statement. Well, now that I think about it it is obvious, because it doesn’t make much sense to switch over something like:

switch (format) {

  case Image.Format.BITMAP: // blah
  case Image.Format.XYPIXMAP: // blah
  case Image.Format.ZPIXMAP // blah
  case  Something.OTHER: // Bad!

}

So it makes sense for the compiler to not accept such code in the first place. I still had some trouble and maybe this post saves somebody some time.

Advertisements

4 Responses to Java Enums

  1. Your id() approach is a good demonstration of how methods in enums generally work. But readers should be aware that for that particular case, you’re really only reimplementing ordinal(), functionality which is inherent to and free with enums. 🙂

  2. roman says:

    Haakon, yes you’re right. But in this particular case, the ID (in the X protocol) really hasn’t much to do on the ordinal of the enum. If I ordered them differently, the IDs still must be those that I specified here. Of course, I could have coded up a more useful example, but I was lazy and copy+pasted my code.

  3. I see what you mean, and you’re right, of course.

    By the way, here is a different solution to the same case. It’s less powerful than yours with abstract method implementation per member, but perhaps easier to read if it is clear that the getter implementation will be the same for all cases.

    public enum Format {

    BITMAP(0),
    XYPIXMAP(1),
    ZPIXMAP(2);

    private int _id;

    Format(int id) { _id = id; }
    public int id() { return _id; }

    }

    (Hope the formatting went well)

  4. Fred says:

    I personally really like enums, and will really like to see more of them.
    By the way, one issue you need to be aware of, is that ordinal() and name() of an enum is not a constant (or literal) for the compiler.
    What I mean is that “Format.BITMAP.ordinal()” is not equivalent to “public static int BITMAP = 0;”. But, in fact internally it is totally equivalent since Format.BITMAP is “public static Format BITMAP = new Format(0,”BITMAP”);”.
    That one reason you cannot use ordinal() and name() in annotation for example.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: