Java通用列表<>

时间:2017-02-15 14:34:41

标签: java generics types

我正在尝试做这样的事情:

1。方法

Type ty = entityType.getEntityClass(); // could be e.g. String.class  
List<ty> list;

2。方法

Class cl = entityType.getEntityClass(); // could be e.g. String.class
List<cl> list;

然而,编译器只是说&#34; no&#34;。

有没有办法设置例如<T>的泛型类型java.util.List动态只有通过例如String.classfoo.getClass()

...

我实际上要做的是按照EntityTypeEnum类型的给定参数或它的Class属性值初始化List。

public enum EntityTypeEnum {
    ARTICLE(Article.class),
    ORDER(OrderHeader.class),
    CUSTOMER(Customer.class),
    CUSTOMER_SESSION(CustomerSession.class);

    private final Class entityClass;

    private EntityTypeEnum(final Class entityClass) {
        this.entityClass = entityClass;
    }

    public Class getEntityClass() {
        return entityClass;
    }
}

建设性的批评是受欢迎的。 谢谢!

  

添加:(作为Andy评论的回应)

Class cl = String.class;
List<cl> list;

..也不起作用!

List<String> list;

..当然有用。

那么StringString.class之间有什么区别?

或者有没有办法将值设置为:

public enum EntityTypeEnum {
    ARTICLE(Article)
..

2 个答案:

答案 0 :(得分:4)

您误解了Java泛型的功能:您无法根据变量的执行某些操作,只能使用变量的类型。< / p>

基本上,Java泛型只是强制类型转换:编译器会自动为您插入强制转换,并检查这些强制转换所产生的类型是否匹配。

你可以做你在你的例子中描述的,但不是使用枚举。 Java中枚举的缺点之一是所有元素都具有相同的类型。

您可以使用大致看起来像枚举的内容,而不是使用真实的枚举:

final class EntityTypeEnumIsh {
  private EntityTypeEnumIsh() {}

  static final EntityClassSupplier<Article> ARTICLE =
    new EntityClassSupplier<>(Article.class);
  static final EntityClassSupplier<OrderHeader> ORDER =
    new EntityClassSupplier<>(OrderHeader.class);
  // ...

  final class EntityClassSupplier<T> {
    private final Class<T> clazz;

    EntityClassSupplier(Class<T> clazz) { this.clazz = clazz; }

    Class<T> getEntityClass() { return clazz; }
  }
}

您现在可以在描述的方法中使用这些:

<T> List<T> method(EntityClassSupplier<T> supplier) {
  return new ArrayList<>();
}

并像这样调用:

List<Article> list = method(EntityTypeEnumIsh.ARTICLE);

当然,你没有获得“真实”枚举的所有优点(如序列化,抵抗反射攻击等)。但是你得到了其他有用的东西,所以要根据你的用例进行衡量。

答案 1 :(得分:1)

它不起作用,因为泛型是一个编译时的概念,但你试图将它用作运行时概念。

不同之处在于,对于编译时概念,编译器需要能够根据代码中的信息确定类型(即,不运行或评估它)。

这里的代码在语法上是正确的:

public enum EntityTypeEnum
{
  ARTICLE(String.class), // just using some builtin types to demonstrate
  ORDER(Integer.class), 
  CUSTOMER(Double.class), 
  CUSTOMER_SESSION(Short.class);

  private final Class<?> entityClass;

  private EntityTypeEnum(final Class<?> entityClass)
  {
    this.entityClass = entityClass;
  }

  public Class<?> getEntityClass()
  {
    return this.entityClass;
  }
}

class Test
{
  // here, T is the type parameter which is determined from the class type
  public <T> List<T> createList(final Class<T> clazz)
  {
    return new ArrayList<T>();
  }

  // this is the demo code on how to use it    
  public void foo()
  {
    EntityTypeEnum t = EntityTypeEnum.ARTICLE;
    List<?> list = createList(t.getEntityClass());
  }
}

问题是这对你没有多大帮助。列表与List大致相同。编译器不能将类型缩小到特定的包含对象类,因为它取决于运行时。

对于您的情况,如果您的元素有一个共同的超类,您可以使用此信息来缩小类型:

public enum EntityTypeEnum
{
  ARTICLE(Article.class),
  ORDER(OrderHeader.class),
  CUSTOMER(Customer.class),
  CUSTOMER_SESSION(CustomerSession.class);

  private final Class<? extends CommonParent> entityClass;

  private EntityTypeEnum(final Class<? extends CommonParent> entityClass)
  {
    this.entityClass = entityClass;
  }

  public Class<? extends CommonParent> getEntityClass()
  {
    return this.entityClass;
  }
}

class Test
{
  public <T extends CommonParent> List<T> createList(final Class<T> clazz)
  {
    return new ArrayList<T>();
  }

  public void foo()
  {
    EntityTypeEnum t = EntityTypeEnum.ARTICLE;
    List<? extends CommonParent> list = createList(t.getEntityClass());
  }
}

但是如果你有一个共同的父母,上面的代码没有好处而只是写作:

List<CommonParent> list = new ArrayList<CommonParent>();

并跳过所有其他通用内容...