JDK-6408723 : Parameterized enum type
  • Type: Enhancement
  • Component: specification
  • Sub-Component: language
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: linux,windows_vista
  • CPU: x86
  • Submitted: 2006-04-05
  • Updated: 2016-11-25
  • Resolved: 2007-02-12
Related Reports
Duplicate :  
Relates :  
Description
A DESCRIPTION OF THE REQUEST :
Enums do not take type parameters.
The following code doesn't compile:

class Property<T> {
  public abstract <T> T accept(Visitor<T> v);
  public static enum Type<T> {
    STRING<String>,
    DOUBLE<Double>;
  }
  public static Property<T> newInstance(Type<T> type, T initValue) {
  switch(type) {
    case STRING:
      return new StringProperty(initValue);
    case DOUBLE:
      return new DoubleProperty(initValue);
    default:
      throw new RuntimeException("invalid enum constant");
    }
  }
}

As well as this code:
public enum UserInfo<T> {
  FirstName<String>,
  LastName<String>,
  UserSince<Date>,
  LastLogin<Date>;
}

public <T> void setUserInfo( UserInfo<T> infoType, T infoValue ) {}


JUSTIFICATION :
Allowing enums to be parameterized allows writing type-safe methods that enforce compile-time consistency between their parameters;
for example, the method:
public <T> void setUserInfo( UserInfo<T> infoType, T infoValue ) {}
which would compile when called on (FirstName, "Mathew"), but issue an unchecked warning or refuse to compile when called with (UserSince, "31/07/2004").

This allows code to be written in a type-safe way when it was impossible before.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The code above compiles without warnings.
ACTUAL -
The above code doesn't compile; the type parameter is rejected by the compiler.

Comments
EVALUATION This proposal really concerns a style of programming whereby enum constants are used as keys that guide the processing of associated objects in a type-safe way. The types of the objects associated with each 'key' (enum constants) are determined by each enum constant's declaration. So for example you have a Username 'key' (enum constant) being associated with a String; more generally each key Ki in the enum is associated with objects of types Ti_1..Ti_n. Because each enum constant knows the types it's associated with, this proposal overcomes one of the objections to generic enums in Angelika Langer's FAQ, i.e. that the type arguments would be unknown for the static members that represent enum constants. The enum constants here are parameterized - STRING<String>, FirstName<String>, LastLogin<Date> - so the objection goes away. I see two problems with the proposed programming style. First, it's straightforward when each enum constant is logically associated with one object, as UserInfo<T> is in the Description. In that case, passing an enum constant and the associated value in a type-safe way is rather neat. But it won't scale when a key is associated with multiple values: enum UserInfo<T,U> { UserAndGroupId<Integer, Integer>; FirstName< String, /* What goes here? */>; LastLogin< Date, /* What goes here? */>; } You could normalize all your keys so they only declare a single type parameter (and hence single object), but this is a very niche programming style. It doesn't justify general language support. JSR201 explicitly specified enums as a simple, popular construct. Second, generic enums would require a big change to compile-time method resolution. Given public <T> void setUserInfo( UserInfo<T> infoType, T infoValue ) {...} calling setUserInfo(FirstName, "...") or setUserInfo(LastLogin, new Date(...)) would have to infer that T is String or Date by inspecting the first argument 'FirstName' or 'LastLogin', rather than just the type of the first argument (which is UserInfo<T>, getting us nowhere in inferring T). Overall, therefore, I believe this proposal has some utility but isn't worth extending the language to support.
12-02-2007