Why shouldn't Java enum literals be able to have generic type parameters?

This has been discussed as of JEP-301 Enhanced Enums, which was withdrawn, regrettably. The example given in the JEP is, which is precisely what I was looking for:

enum Argument<X> { // declares generic enum
   STRING<String>(String.class), 
   INTEGER<Integer>(Integer.class), ... ;

   Class<X> clazz;

   Argument(Class<X> clazz) { this.clazz = clazz; }

   Class<X> getClazz() { return clazz; }
}

Class<String> cs = Argument.STRING.getClazz(); //uses sharper typing of enum constant

Unfortunately, the JEP was struggling with significant issues, which couldn't be resolved: http://mail.openjdk.java.net/pipermail/amber-spec-experts/2017-May/000041.html


The answer is in the question:

because of type erasure

None of these two methods are possible, since the argument type is erased.

public <T> T getValue(MyEnum<T> param);
public T convert(Object);

To realise those methods you could however construct your enum as:

public enum MyEnum {
    LITERAL1(String.class),
    LITERAL2(Integer.class),
    LITERAL3(Object.class);

    private Class<?> clazz;

    private MyEnum(Class<?> clazz) {
      this.clazz = clazz;
    }

    ...

}

Because you can't. Seriously. That could be added to the language spec. It hasn't been. It would add some complexity. That benefit to cost means it isn't a high priority.

Update: Currently being added to the language under JEP 301: Enhanced Enums.


There are other methods in ENUM that wouldn't work. What would MyEnum.values() return?

What about MyEnum.valueOf(String name)?

For the valueOf if you think that compiler could make generic method like

public static MyEnum valueOf(String name);

in order to call it like MyEnum<String> myStringEnum = MyEnum.value("some string property"), that wouldn't work either. For example what if you call MyEnum<Int> myIntEnum = MyEnum.<Int>value("some string property") ? It is not possible to implement that method to work correctly, for example to throw exception or return null when you call it like MyEnum.<Int>value("some double property") because of type erasure.