Java枚举文字为什么不能有泛型参数? [英] Why shouldn't Java enum literals be able to have generic type parameters?

查看:132
本文介绍了Java枚举文字为什么不能有泛型参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java枚举很棒。仿制药也是如此。当然,我们都知道后者的局限性是因为类型擦除。但是有一件事我不明白,为什么我不能创建这样的枚举:

  public enum MyEnum< T> {
LITERAL1< String>
LITERAL2< Integer>
LITERAL3< Object> ;;
}

此通用类型参数< T> code>然后可以在各个地方有用。想象一下一个方法的通用类型参数:

  public< T> T getValue(MyEnum& T> param); 

甚至在枚举类本身:

  public T convert(Object o); 



更具体的例子#1



上面的例子似乎对于某些人来说似乎太抽象,这里是一个更现实的例子,为什么我想这样做。在这个例子中,我想使用




  • 枚举,因为我可以枚举一组有限的属性键

  • 因为那时我可以使用方法级的类型安全来存储属性




  public interface MyProperties {
public< T> void put(MyEnum< T> key,T value);
public< T> T get(MyEnum< T> key);
}



更具体的示例#2



我有枚举数据类型:

  public interface DataType< T> {} 

public enum SQLDataType< T>实现DataType< T> {
TINYINT< Byte>
SMALLINT< Short>
INT< Integer>
BIGINT< Long>
CLOB< String>
VARCHAR< String>
...
}

每个枚举字面值显然具有基于通用类型< T> 的其他属性,同时作为枚举(不可变,单例,可枚举等) p>

问题:



没有人想到这个?这是编译器相关的限制吗?考虑到这个事实,关键字枚举被实现为语法糖,表示生成的代码到JVM,我不明白这个限制。



谁可以向我解释一下?在您回答之前,请考虑以下事项:




  • 我知道通用类型被删除: - )

  • 知道有使用Class对象的解决方法。它们是解决方法。

  • 通用类型会导致编译器生成的类型转换(如果适用)(例如,当调用convert()方法时

  • 通用类型< T>将在枚举上,因此它被每个枚举的文字所约束,因此编译器将知道在写入如$ code> String string = LITERAL1.convert(myObject)时应用哪种类型, ;整数integer = LITERAL2.convert(myObject);

  • 同样适用于 T getvalue() / code>方法编译器可以在调用 String string = someClass.getValue(LITERAL1)

时应用类型转换

解决方案

现在正在 JEP- 301增强枚举。JEP中给出的示例正是我正在寻找的:

 枚举参数< X> {//声明通用枚举
STRING< Str (String.class),
INTEGER< Integer>(Integer.class),...;

类< X> clazz中;

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

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

类< String> cs = Argument.STRING.getClazz(); //使用更清晰的枚举类型常量


Java enums are great. So are generics. Of course we all know the limitations of the latter because of type erasure. But there is one thing I don't understand, Why can't I create an enum like this:

public enum MyEnum<T> {
    LITERAL1<String>,
    LITERAL2<Integer>,
    LITERAL3<Object>;
}

This generic type parameter <T> in turn could then be useful in various places. Imagine a generic type parameter to a method:

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

Or even in the enum class itself:

public T convert(Object o);

More concrete example #1

Since the above example might seem too abstract for some, here's a more real-life example of why I want to do this. In this example I want to use

  • Enums, because then I can enumerate a finite set of property keys
  • Generics, because then I can have method-level type-safety for storing properties

public interface MyProperties {
     public <T> void put(MyEnum<T> key, T value);
     public <T> T get(MyEnum<T> key);
}

More concrete example #2

I have an enumeration of data types:

public interface DataType<T> {}

public enum SQLDataType<T> implements DataType<T> {
    TINYINT<Byte>,
    SMALLINT<Short>,
    INT<Integer>,
    BIGINT<Long>,
    CLOB<String>,
    VARCHAR<String>,
    ...
}

Each enum literal would obviously have additional properties based on the generic type <T>, while at the same time, being an enum (immutable, singleton, enumerable, etc. etc.)

Question:

Did no one think of this? Is this a compiler-related limitation? Considering the fact, that the keyword "enum" is implemented as syntactic sugar, representing generated code to the JVM, I don't understand this limitation.

Who can explain this to me? Before you answer, consider this:

  • I know generic types are erased :-)
  • I know there are workarounds using Class objects. They're workarounds.
  • Generic types result in compiler-generated type casts wherever applicable (e.g. when calling the convert() method
  • The generic type <T> would be on the enum. Hence it is bound by each of the enum's literals. Hence the compiler would know, which type to apply when writing something like String string = LITERAL1.convert(myObject); Integer integer = LITERAL2.convert(myObject);
  • The same applies to the generic type parameter in the T getvalue() method. The compiler can apply type casting when calling String string = someClass.getValue(LITERAL1)

解决方案

This is now being discussed as of JEP-301 Enhanced Enums. 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

这篇关于Java枚举文字为什么不能有泛型参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆