Java: Customizing enums

After reading this you might wonder why I would write about something obvious like that. And I agree. It is quite obvious. Once you know about it. However, first I didn't know and neither did the other Java programmers I've spoken to. So I thought it's worth writing up a quick blog post.

Probably all of you already know about enums and use them as type-safe flags or enumerations:
enum Cardsuit { CLUBS, DIAMONDS, SPADES, HEARTS };
That is pretty basic and probably everyone learned that in Java 101. What was new to me, though, is that you can customize the enum { } pretty much like a class.

So for example, one day I was working on a XML parser implementation, where depending on an attribute value of a XML element I had to make a decision. Since in XML everything is a String I wrote a quick method which compares an enum to a String. But I didn't know where to put it in my code. I figured the best place would be within the enum itself. Not really thinking that it would work, but still curious I tried the following:
I tried to compile it and voilà: it worked! No errors, no warnings.

In my actual XML parser I then would only have to do the following:
if ( Cardsuit.CLUBS.compareToString(xmlString) ) { .... }
Of course there would have been many other ways to do this, but this solution seems quite clean and elegant to me.

1 comment:

  1. Most Java programmers have no idea of what enums can do, and how useful they can be.

    As Josh Bloch wrote in Effective Java, Enums can be used to implement the singleton pattern (for what it's worth).

    Enums can implement interfaces, can hold fields and methods, can have constructor parameters. Methods in enum can be overridden.

    The only tricky part to know is that enum constructors are called BEFORE any static enum init block. That's because enum values are static, and are created before evaluation of any static init block.

    Just for fun, I just wrote a piece of code that shows some of those features. Could you guess the output of the following code ?

    public enum EnumFun implements Callable {


    LOAD_TIME(EnumFun.class.getSimpleName() + " was loaded at") {
    private final Date loadTime = Calendar.getInstance().getTime();

    @Override
    protected String getValue() {
    return loadTime.toString();
    }
    },
    DECLARED_FIELDS("Fields") {

    @Override
    protected String getValue() {
    return Arrays.asList(EnumFun.class.getDeclaredFields()).toString();
    }

    };

    static {
    System.out.println("in static enum init block");
    }

    public static void callEach() throws Exception {
    for(EnumFun enumFun : values()) {
    System.out.println(enumFun.call());
    }
    }


    private final String description;

    EnumFun(String description) {
    this.description = description;
    System.out.println("in constructor of " + name());
    }

    @Override
    public final String call() throws Exception {
    return String.format("%s : %s", description, getValue());
    }

    protected abstract String getValue();

    public static void main(String[] args) throws Exception {
    callEach();
    }

    }

    ReplyDelete