views:

138

answers:

4

Recently I've been doing a lot of these

enum Thing {

    /* etc etc */

    static final Set<Thing> allThings = EnumSet.allOf(Thing.class);

}

I want something similar in pre 1.5 Java, i.e. I want something like:

final class Thing {

    private Thing(); // control instances within class

    static final Thing instance0 = new Thing();
    static final Thing instance1 = new Thing();

    static final Set allThings = // ?????
}

How should I do this?

+2  A: 

There was no direct equivalent in pre-1.5 Java.

Before Java 1.5, there were two (syntactically quirky) options if you wanted to initialize immediately:

static final Set allThings = new HashSet(Arrays.asList(new Object[] {
    instance0, instance1, // etc.
}));

or

static final Set allThings = new HashSet() {{
    add(instance0);
    add(instance1);
    // etc.
}};

Both of these have their drawbacks, though. The simpler way is to simply make a static method

private static Set all() {
    Set ret = new HashSet();
    ret.add(instance0);
    ret.add(instance1);
    // etc.
}

You still have to remember to add any new members to the method, but it's easier to read (for most people).

Michael Myers
+3  A: 

What about that:

final class Thing {

  static final Set allThings = new HashSet();

  private Thing() {
      allThings.add(this);
  } // control instances within class

  static final Thing instance0 = new Thing();
  static final Thing instance1 = new Thing();
}
pgras
+1  A: 

There's a pretty well-defined pattern on how to define typesafe enums in a pre-Jav 5 environment.

It's basically a class with public final static fields for the values and a private constructor (or more).

The only "hard" thing is getting details like serialization right (basically by implementing readResolve()).

This Javaworld Tip goes pretty in-depth on the matter and this one has some more to say on the subject.

Joachim Sauer
A: 

In the following solution, each enum class extends an abstract base class AbstractEnum, and has its own set of all values automatically generated and stored in a static map in the base class.

 public abstract class AbstractEnum
  {
    private final static Map/*<Class,Collection<AbstractEnum>>*/ allEnums 
      = new HashMap();

    protected AbstractEnum()
    {
      Collection/*<AbstractEnum>*/ allValues 
        = (Collection) allEnums.get(getClass());
      if (allValues == null)
      {
        allValues = new HashSet();
        allEnums.put(getClass(), allValues);
      }
      allValues.add(this);
    }

    protected static Collection/*<AbstractEnum>*/ getAllValues(Class clazz)
    {
      return Collections
        .unmodifiableCollection((Collection) allEnums.get(clazz));
    }
  }

  final class Thing extends AbstractEnum
  {
    final static Thing thing0 = new Thing();

    final static Thing thing1 = new Thing();

    private Thing()
    {}

    static Collection/*<Thing>*/ getAllValues()
    {
      return getAllValues(Thing.class);
    }
  }

Note that it still needs some additional important features, such as thread-safety and serialization (as described in the post by saua).

Bartosz Klimek