miercuri, 1 februarie 2012

Java Enums. The “non obvious” way to cast to an int and vice versa

Enums are usually stored as ints in most programming languages. Those languages usually allow the programmer to freely convert between the enum and the underlying integer value, but Java doesn’t want you to do that. I want to do this:

private enum Command = { stop, start} // stop = 0, start = 1

Command myCommand = start;

int value = (int)myCommand; // won’t compile

Command aCommand = (Command)1; // also won’t compile

There’s no shortage of Java programmers who will tell you that trying to perform the above is “bad” practice. Their reasoning goes something like if you trying to convert an enum to an int they you are using the enum wrong. Sure if you are using the enum in something like a switch statement then there’s no need to convert it to an int. However, as soon as you are trying saving that enum to a file, or send it over a network connection, or set it as a field in a sql statement, it’s not going to work. The problem is that the file doesn’t have any idea (nor does it care) about Java enums. TCP/UDP doesn’t understand Java enums either. It’ll handle byte streams just fine, but to convert your enum to a byte stream first you have to convert it to an int. Lastly, I have yet to see a database that accepts a Java enum as a field. They basically all accept ints though.

Which leads us back to our problem. We want to convert our enum to and/or from an int. I’ve seen many elaborate (read: hacked) ways of doing it. I’ve done it myself. It turns out there’s a fairly easy (but non-obvious) way to do it:

Command myCommand = start;

int value = myCommand.ordinal(); // works as expected; although the java docs complain about this usage

Command aCommand = Command.values()[1]; // also works

There’s a Java programmer out there somewhere right now trying to convert his ints to an enum.

source: http://www.chippeddagger.com/2010/04/17/java-enums-the-non-obvious-way-to-cast-to-an-int-and-visa-versa/