Back to Top

Tuesday, November 11, 2008

Enumerations in Java

Starting to (professionally) program in Java, one of the things which bugged me were the constant declarations in classes which implemented struct-like idioms:

class Foo {
  public static final int FOO_1 = 1;
  public static final int FOO_2 = 2;
  public static final String FOO_3 = "42";
  ...

The code referencing this seems even more clumsy, especially in the case of equality testing:

  ...  Foo.FOO_3.equals(someVariable) ...

This seems to me vastly inferior (from the point of view of readability) to this:

  ...  Foo.FOO_3 == someVariable ...

There are two things going for this: there is less characters to type (even with Eclipse auto-complete :-)) and also the "==" operator provides a nice visual separation of the two parts. Then I remembered reading about the technique called type-safe enums. Even better, I found that this method is included in the language since version 1.5 (AKA Java 5.0) and gives you several nice features:

  • Handles serialization and deserialization automatically (no need for you to write code)
  • Can be used in switch statements
  • Supports adding additional methods/data (this is important if the enumeration needs to interface with systems outside of the JVM which use an "encoded" version of the enumeration - for example and integer number)

Unfortunately I also found a big, big problem with this approach: it doesn't work when multiple ClassLoaders are involved (see the printer friendly version and an other discussion ). Now you probably will go (like I did) WTF are multiple class loaders and when will I encounter them? The two linked articles do a good job of explaining (also, take a look at the comments), so I will highlight just two usecases which you might encounter:

  • Using Applets (applets from different pages are loaded by different ClassLoader's for security reasons)
  • Using application containers like Tomcat, WebLogic, etc (again, classes from different deployment entities - wars / ears - will be loaded by different class loaders because of security considerations) - see for example this article from TheServerSide.com which explains it in more detail.

So where does this leave us? The current solution I see is:

  • Use the typesafe enum pattern (together with the serialization part)...
  • but don't use "==" if there is the slightest chance that you will get in a multi-classloader situation (from my current understanding this means Applets - not so common - or applications servers - common). Instead implement an equals and hashCode method (remember the restrictions correct implementations of the methods must respect) and use the equals method.
  • When these constraints don't apply, you can use enums (supposing that you target Java 1.5+). You can't override equals for enums, because it is marked as final in the parent :-(.

So where does this leave us?

This solves the typesafety issue (meaning that you no longer have methods which accepts three int's, but a method which accepts a parameter of type Foo, one of type Bar, etc - this means that there is less of a chance for mixing up the parameter order for example).

However, this still doesn't solve the elegance problem, which is very important (the less you have to write, the less chance you have to screw it up - also, it is easier for those who come after us to read the code).

0 comments:

Post a Comment

You can use some HTML tags, such as <b>, <i>, <a>. Comments are moderated, so there will be a delay until the comment appears. However if you comment, I follow.