Featured Whitepapers
Newsletter sign-up
View all newsletters

Sign up for our technology specific newsletters.

Enterprise Java
Email Address:

Java Tip 122: Beware of Java typesafe enumerations

Think twice before relying on instance identity

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone

Page 2 of 3

This could lead to unexpected results in runtime environments like an EJB container, especially since most EJB containers support optimization options to disable the serialization marshalling of method arguments for beans deployed in the same JVM. Your code's runtime behavior will then depend on this option's setting -- not a very comforting thought, is it?

As pointed out by Joshua Bloch, we must do more to ensure that serialization doesn't result in illegal Enum instances unexpectedly springing up at runtime. At a minimum, we have to add a readResolve() method and an instance field to use as the real instance ID:

public final class Enum implements java.io.Serializable
{
    public static final Enum TRUE = new Enum (true);
    public static final Enum FALSE = new Enum (false);

public String toString () { return String.valueOf (m_value).toUpperCase (); }
private Enum (boolean value) { m_value = value; }
private Object readResolve () throws java.io.ObjectStreamException { return (m_value ? TRUE : FALSE); }
private boolean m_value;
} // end of class


Here, in the readResolve() method, I check the value ID of the instance just created and replace the deserialized instance with one of the static objects.

Unfortunately, many programmers today are unaware they must implement readResolve() to perform instance substitution during serialization (this feature was not available before Java 2 either). If we don't do this, however, we won't get any compiler or runtime errors -- the reference comparison will simply fail each time we compare an Enum value against a deserialized Enum instance. Depending on the enumeration's size, the amount of work necessary to have a correct and serializable typesafe class may be too much compared to the good old "typeunsafe" pattern (the standard practice of defining simple-minded sets of constants referred to earlier), which lacks this issue.

Interestingly enough, Sun's JDK uses the typesafe enum pattern and is not consistent with making all such types Serializable: several Swing typesafe enum classes are not Serializable (for example, javax.swing.text.html.HTML.Tag), while others are (for example, java.util.logging.Level in JDK 1.4+).

Dealing with classloaders

Another scenario in which the typesafe enum pattern breaks completely is when the Java runtime loads the Enum class multiple times. Although this sounds obscure, it can happen more easily than you might think.

Consider an EJB invoking a method on another EJB. If the EJBs come from different deployment JAR units, different classloaders may load them. Both deployment JARs could package the Enum class, and the particular details of the container classloader hierarchy can conspire to have both classloaders load the Enum twice. If the two EJBs then exchange data that includes the Enum type and the data is not marshalled by means of serialization, relying on object reference identity for comparison will most certainly fail.

Consider another possibility: a JavaServer Page (JSP) or a servlet placing data that includes Enum instances in an HTTP session. If the servlet later reloads (for example, because the JSP updates) and then attempts to compare anything against Enum values left in the session, this will create the same effect of a class in one classloader namespace acquiring data from a different classloader namespace.

  • Digg
  • Reddit
  • SlashDot
  • Stumble
  • del.icio.us
  • Technorati
  • dzone
Comments (2)
Login
Forgot your account info?

I'm surprised to see such an article on JavaWorld...By Anonymous on May 18, 2009, 5:22 amI'm surprised to see such an article on JavaWorld. I couldn't disagree more with your statements, especially about how enums are a poor substitutes for static ints....

Reply | Read entire comment

Upcasting typesafe enumsBy Anonymous on December 4, 2008, 7:31 pmOnce the Serialization issue is fixed, typesafe "enum" style classes can be safely compared with == provided the variables are declared as the Enum class, and not...

Reply | Read entire comment

View all comments

Add comment
Anonymous comments subject to approval. Register here for member benefits.
Have a JavaWorld account? Log in here. Register now for a free account.
Resources