The Source for Java Technology Collaboration
User: Password:



Michael Nascimento Santos

Michael Nascimento Santos's Blog

Writing enums before Tiger

Posted by mister__m on December 10, 2003 at 10:46 PM | Comments (12)

One thing I've been missing in Java is support for enums. Some of you might be asking: but what is a enum and why should I care about them? A enum is, in a simple way, a class with a limited domain. For example, a class representing the seasons we have during the year - although climate seems crazy these days, anyway, but that's a different story - is a enum. Another example would be a class that represents gender, as it only has two values, male and female (though, again, some might argue it is not that simple :-D).

Enums for J2SE 1.5 are being defined by JSR-201. I recommend you read the draft spec when you have the chance, but I'll cite the relevant points as needed. First, let's take a look at the main features both - my implementation and the future J2SDK 1.5 one - share, as specified by the draft spec at the JCP site:

  1. Compile-time type safety
  2. Performance comparable to int constants.
  3. Type system provides a namespace for each enum type, so you don't have to prefix each constant name.
  4. Typesafe constants aren't compiled into clients, so you can add, reorder or even remove constants without the need to recompile clients. (If you remove a constant that a client is using, you'll fail fast with an informative error message.)
  5. Printed values are informative. (Which would you rather see in a stack trace: "Indigo" or "6?")
  6. Enum constants can be used in collections (e.g., as HashMap keys).
  7. You can add arbitrary fields and methods to an enum class.
  8. An enum type can be made to implement arbitrary interfaces.

How is it possible to achieve these things now? By using the Enum class provided by my open-source project, reusable-components! Here is a code snippet:

import net.java.dev.reusablecomponents.lang.Enum;

public final class Gender extends Enum implements MyInterface {
   public static final Gender MALE = new Gender("Male");
   public static final Gender FEMALE = new Gender("Female");

   private Gender(String name) {
      super(name);
   }
}

In this example, MyInterface is a simple marker interface that is implemented just to show you it is possible to do so. :-D The code doesn't look that complicated, but it gives you all those things and also these additional features quoted from the JCP spec:

All enum classes have high-quality toString, hashCode, and equals methods. All 
are Serializable, Comparable and effectively final. None are Cloneable.
Arbitrary fields may be added to enum classes, and to individual enum constants.

To be exact, you have to make your Enum subclasses final. If you subclass an Enum subclass, it simply won't work. However, the greatest feature these Enum subclasses have is that their instances may be compared using the == operator. Even if you deserialize an instance, you still can use the operator instead of calling equals. Isn't that great? I think so, but I'm not neutral enough to give opinions about code I wrote. :-D

Surely, there are some differences between my Enum and the one provided by the JSR-201. I hope to explain most of them here, but to be sure you understand all the differences, read the spec linked above and browse the most recent version of my Enum implementation.

While the J2SE 1.5 enum is intended to give you comparability, it limits the way you naturally compare your instances by making compareTo final. reusable-components' implementation doesn't make the method final, giving you freedom to override it as needed. Besides that, JSR-201 is going to give as an enum facility, which is something much bigger than just a class: we will have a new keyword, new syntax and more compiler "gambiarras", as we would say in Portuguese: the compiler is going to make lots of things to your source code to make it look like a regular class. To give you an idea of what the J2SE 1.5 enum probably is going to be like, here is the original example modified:

public enum Gender implements MyInterface {
   male, female
}

Although it is by far cleaner than the code I showed above, it requires special compiler features and most IDEs won't support it now.

Maybe you could be thinking: but why I need to use a superclass if I can write an enum implementation on without one? Well, you would have to rewrite things you need, such as serialization and == support, for example. The fact you have a base class also helps to organize your code and to evolve it as you find bugs.

Now that I gave you a general idea of what net.java.dev.reusablecomponents.lang.Enum can do, it is time to mention a few more things. There are methods that allow you to get all the instances for a given subclass and to get an instance given its class and its identifying name. Those methods are especially useful if you are using enums as part of a web application: you need to populate combos and to get the selected instance to do your job.

If you are interested enough, I recommend you check the code. You can ask questions and leave your comments below. reusable-components is intended to give you more than that, though; in the next few weeks, I expect to commit some validators for user input and also a cool image generator for use in forms to make sure users aren't frauding your application. Join the project if you want to help. And stay tuned.


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • Jakarta Commons
    Jakarta Commons has a similar goal to your reusable-components project. Indeed, the "lang" subproject has a Enum implementation. You might want to check that project out, and possibly contribute to it.

    Jakarta CommonsJakarta Commons langEnum java doc

    Posted by: jimothy on December 11, 2003 at 05:23 AM

  • Re: Jakarta Commons
    To be honest, I haven't seen their implementation, but there are some major differences between them. First, the methods that return all the instances and return a specific one based on its name are public in my version. I also provided an internal ordinal you can use as needed.
    There is also a problem with Apache: it is really hard to become a committer. I wouldn't mind helping them, but I doubt it they would let me be a committer until I made a number of contributions. It is an organization and it takes time to get the needed permissions, even when you are approved - a friend of mine has been waiting for a looong time just to get the papers he has to sign in before becoming a committer.
    To end up with, our project goals are different: reusable-components is going to give you things you want to use daily, such as validators, image generator servlets for forms and more. Jakarta Commons is more about common infrastructurel; I like some of their projects very much, such as JXPath, which I use to query Prevayler databases. Thanks for expressing your opinion.

    Posted by: mister__m on December 11, 2003 at 05:35 AM

  • Re: Jakarta Commons
    There's also a Jakarta Commons Validator. :)

    A lot of the subprojects, lang and collections in particular, really are quite useful for daily coding work. I'd encourage you to take another look at them.

    I do understand your concerns with regard to contributing and committing (but I also understand why such policies would exist).

    Good luck with reusable-components. It'll be interesting to see how it evolves.

    Posted by: jimothy on December 11, 2003 at 06:21 AM

  • Re: Jakarta Commons
    I am aware of that one :-D
    However, the validators I intend to provide, in fact, will be Jakarta Commons Validator implementations for some Brazilian specific IDs, for example. And there will also be InputValidations for Swing components for a large range of data - not just Brazilian specific - , which are very long needed.
    I know most Jakarta Commons except for Lang; the last time I took a look at it they just had helper classes for toString, equals and hashCode implementations, so I overlooked it. Our goals here are different and reusable-component is a Brazilian Java community effort, which means it will provide some components that are useful just for Brazilians. Many of them, however, will be of general interest and that is one of them.
    Again, thanks for your interest. You can email me at mister__m at dev.java.net if you want.

    Posted by: mister__m on December 11, 2003 at 06:30 AM

  • EnumSyntax
    In JDK 1.4, you can subclass javax.print.attribute.EnumSyntax to create new typesafe enum classes. It deals with serialization and the other enum issues.

    Posted by: wire on December 11, 2003 at 07:55 AM

  • Re: EnumSyntax
    This class was intended for printing attributes and it works pretty well for that cases. However, it has some undesired shortcomings: you must provide an integer at instantiation time, even if you don't need one. Also, you must override two methods to make your Enum works properly, besides the constructor, which is, by the way, mistakenly not overriden in the sample code they provide. Besides that, there is no support for implicit comparisson based on order of declaration, which might be useful and is part of reusable-components implementation.
    To make it clear, the Enum implementation I wrote is intended to work as close as possible as the J2SE 1.5 one, except for some differences that comes from the fact I'm writing a class and they are giving us a facility with built-in compiler support.

    Posted by: mister__m on December 11, 2003 at 09:11 AM

  • Java Tip 133: More on typesafe enums
    See also:

    Substitutes for C Constructs in
    Effective Java
    http://java.sun.com/developer/Books/effectivejava/Chapter5.pdf

    Java Tip 133: More on typesafe enums
    http://www.javaworld.com/javaworld/javatips/jw-javatip133.html

    Every Java programmer should read "Effective Java".

    Posted by: coxcu on December 11, 2003 at 01:03 PM

  • Re: Java Tip 133: More on typesafe enums
    I've read these materials before. The type-safe enum implementation provided by reusable-components is, in fact, better than the one proposed by Effective Java. The new enum facility in Tiger is also better than this one.
    I agree with your comment about Effective Java: terrific book, a must-read.

    Posted by: mister__m on December 11, 2003 at 01:09 PM

  • Re: Jakarta Commons
    You don't need to be a committer to contribute to any jakarta project. To contribute, you can submit patches, but to be honest: usually the jakarta-commons projects are quite usefull as they are.

    Posted by: ned___flanders on December 12, 2003 at 02:07 AM

  • Re: Jakarta Commons
    It is possible to contribute small pieces of code, but you need a committer to actually make it part of the code base. Besides that, changing a concept in a component is something more difficult than what you described that.
    I agree that usually jakarta commons is good as is - and I have to mention JXPath again, great API -, but reusable-components doesn't intend to replace commons in anyway (maybe just the Enum implementation, ok, but it has a different purpose anyway).

    Posted by: mister__m on December 12, 2003 at 07:54 AM

  • nice work!
    michael, nice work. in a previous project i created a "layer supertype" for typesafe enums, but it wasn't as robust as yours. i especially like its support for anon-inner subclasses of the enum for supporting enums with behavior.

    Posted by: pholser on September 08, 2004 at 09:10 AM

  • Thank you very much for your implementation of Enum We use it in our application. We also use Jakarta Commons Enum, and we are trying to standardize on a single implementation. We like that your Enum does not require a utility class like org.apache.commons.lang.EnumUtils. However, the following comment in the JavaDocs of your implementation concerns us:

    Subclasses should be final, as most methods provided in this superclass won't work for subclasses of subclasses.

    Similarly, you say above If you subclass an Enum subclass, it simply won't work

    What does this mean? We haven't seen these problems with your implementation of Enum, but we are nervous that we don't have a sufficient test case to discover the problem. Could you explain how subclassing subclasses fails with this implementation?

    Posted by: lmfinney on January 20, 2005 at 08:26 AM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds