从Java中的枚举属性获取泛型类的实例

时间:2014-09-26 21:39:37

标签: java generics casting enums

我的班级中有一个包含Class属性的枚举,如下所示:

public enum DatEnum {
  CONSTANT_ONE(ClassOne),
  CONSTANT_TWO(ClassTwo);

  private Class<? extends UpperBoundClass> classAttribute;

  private DatEnum(Class<? extends UpperBoundClass> classAttribute) {
    this.classAttribute = classAttribute;
  }

  public <T extends UpperBoundClass> T getInstance() {
    UpperBoundClass instance = classAttribute.newInstance();
    return instance;
  }
}

但接着我在吸气剂的第一行发出警告:

  

从捕获#4中取消选中?将UpperBoundClass扩展为T

并且在吸气剂的第二行:

  

取消选中从UpperBoundClass到T

的强制转换

到目前为止,代码有效,但我真的想摆脱警告,以及更好地了解这里的问题。

2 个答案:

答案 0 :(得分:1)

public <T extends UpperBoundClass> T getInstance() {
  UpperBoundClass instance = classAttribute.newInstance();
  return instance;
}

此代码实际返回<T> 。它返回Class<? extends UpperBoundClass>字段引用的特定classAttribute的实例。所有编译器都可以验证instance是否可赋予(能够转换为)UpperBoundClass。但是,该实例与方法签名中由<T>表示的特定类型之间没有声明的关系。

最终结果:您将收到警告。只要您使用CONSTANT_ONECONSTANT_TWO的每个地方都期望与您在各自的构造函数中放置相同的类型,它就可能正常工作,但编译器可以&#39 ;强制或知道。

如果您将方法更改为以下内容,那么您将看到非严格类型安全的使用网站(在调用代码中),因为它们假设了一个特定的子类:

public UpperBoundClass getInstance() {
  return classAttribute.newInstance();
}

或者,您可以在<T>和存储的类引用之间提供一些关系:

public <T extends UpperBoundClass> T getInstance(Class<T> type) {
  UpperBoundClass instance = classAttribute.newInstance();
  return type.cast(instance); // verifies type-safety
}

但这样做有一点重要,因为调用者可以自己调用type.newInstance(),也可以只调用new ClassOne()(具体取决于用例)。对type.cast(instance)的调用可能会在运行时抛出ClassCastException,但编译器会很高兴因为它在那时认为它是你的问题。

您正在与 enum提出统一合同 这一事实作斗争;虽然您可以使用多态行为自定义单个常量,但您不能使用泛型来参数化enum 基本API ,其中包含因实例而异的内容。

相关阅读:Why shouldn't Java enum literals be able to have generic type parameters?

答案 1 :(得分:0)

首先,您的enum类没有枚举常量。其次,我相信您的Enum对象将Class Object作为其变量变量。在大多数情况下,每个类都有一个Object(除非你使用多个classLoaders来加载一个类),所以为什么不使用只包含Class Objects的简单数据结构。

实际上,您始终可以使用Class.newInstance()Class.getDeclaredConstructors()来获取Constructor并起诉它拥有自己的实例。