The Study of Ajax and Other Interesting Web Technologies

Making the Most of Java 5.0: Enum Tricks

So your organization has finally moved to Java 5.0...and you are wondering what you can do with some of its new features. In this first of a series of articles on Java 5.0, I'll show you some of the interesting ways that you can exploit the new language features to improve the way you code Java.

First off, enumerations.

Introduction to Enums

The enumeration is a way of creating self-documenting code, a big improvement over the "magic" integer or string constants which are often used to represent a defined set of values. Enumerations abound in object models, and examples are not hard to find: days of the week, colors, card suits, etc. The idea of enumerations as an actual programming language type goes back to Pascal. Many programmers, though, are likely to be more familiar with the C/C++ version of it as the enum, which is just a decorated integer:

In Java, the introduction of enumerations started informally with Joshua Bloch's type-safe enumeration pattern. The pattern boils down to essentially this: a Java class with a private constructor that declares public static final versions of itself.

public final class Suit {
private Suit() {}
public static final Suit SPADES = new Suit();
public static final Suit HEARTS = new Suit();
public static final Suit DIAMONDS = new Suit();
public static final Suit CLUBS = new Suit();
}

Figure 2: The type-safe enumeration pattern

The advantage of this style of enumeration over the C/C++-style enum or constants is that they are "type-safe", meaning that, for example, if you define a method

public void setSuit(Suit suit) { ... }

the caller cannot pass in a value that does not correspond to an enumeration value. With a constant or C/C++-style enum, you could pass in a random value (like -1) that would not. Java-style enumerations have the additional advantage that, since they are classes, you can "associate" other data with them. This idea will be illustrated a little later. Since these enumeration instances are all effectively singletons, they can be compared for equality using identity ("==").

Enums in Java 5.0

In Java 5.0, the enum keyword is introduced as a special type of class that always extends java.lang.Enum. These closely resemble an abbreviated version of Bloch's type-safe enumeration pattern.

The difference is that this version includes utility methods like name() that returns the declared variable name as a String, ordinal() that returns the position of the enum as it is declared in the class, and valueOf() which allows you to look up the enum using its declared variable name as a String. Java 5.0 enumerations also can be used in switch statements, a nice convenience. Note that the enumeration values are still static class members, though not declared as such.

So, going beyond the basics, what can you do with Java enumerations? Here are a few handy tricks...

Enums and Template Methods

Remember that the enum is basically a special class type, and can have methods and fields just like any other class. Remember also that each declared field is also an instance of the enum. So, applying the "Template Method" design pattern, one can create enumerations that are factories or command objects, but a defined set of objects. Here is a simple example of a "command" enumeration:

With the use of static imports, the client code calling this enumeration would look like:

SOLDIER.execute();
DOLL.execute();
//or better...
getToy().execute();

The resulting code is clear and self-documenting. Using this pattern is a great alternative in many cases to the more common if(toy=="soldier"){...} else if(toy=="doll"){...} else{...} logic since it is easier to read, extend, and maintain.

Reverse Lookups

Often in your object model it is common to have data that is naturally "associated" with an enumeration. Since an enum is a class, it is easy to represent this associated information as class fields. Often it is desirable to "lookup" the associated enumeration using the field value. This is easy to do using a static java.util.Map. Take, for example, a Status enum that has an associated status code.

The static get(int) method here provides the reverse lookup by simply getting the value from the Map. The static block to populate the Map uses a specialized implementation of Set, java.util.EnumSet, that "probably" (according to the javadocs) has better performance than java.util.HashSet. Java 5.0 also provides java.util.EnumMap, a specialized implementation of Map for enumerations that is more compact than java.util.HashMap.

Conclusion

The enum in Java 5.0 represents a cleaner, more self-documenting, richer, and in many cases, more efficient way of coding certain object model concepts than was possible using the older idiom of static final constants. Even if you are still using Java 1.4.x or earlier, you can still gain many of the benefits of the enum by using the type-safe enumeration pattern; this will also make the code easier to migrate once you do go to Java 5.0. Older client code that uses constants can still be adapted to use the enum by associating constant values with the enumerations themselves (as seen in the Status class, Figure 5). So, in other words, there is no reason not to convert your old static constants to enumerations. The guy who has to maintain your code will thank you.

Yes, you're right (the final keyword should not be there). Enums are effectively final (you cannot extend them with other enums), but only after they have been subclassed by internal implementations of the class (which is why you are able to use the template method). I've edited the example with the correction.

Yeah, being able to model, e.g., a state machine with an enum would be very cool. If I had my choice, though, I would have enums that can (optionally) be some other type, e.g. an enum of Strings. Hence they could function like restrictions in XSD.

Instance methods declared in these class bodies are may be invoked outside the enclosing enum type only if they override accessible methods in the enclosing enum type.

The reason is simple: a SomeEnum.SOME_ENUM enum returns to the LHS a reference to the enclosing enum class and not the anonymous inner sub-class that is created with each enum instance. Hence you must have the method declared in the body of the enum class to be referenceable in this case.

Try declaring testMethod() as a TestEnum method stub and then overriding it in ENUM_CONST1

NB. I have not personally tested the validity of this suggestion due to a lack of a ready compiler but intuition tells me this is the natural extension (of the previous poster's explaination) that should produce the effect you desired.

Java is the most important language now-a-days in web development..
It is used worldwide on a large scale..
Creating custom Enums in Java is a great boon.. Also the templates are of a great use..
Thanks for this information..
It will definitely help Java Developers on a large scale.