繁体   English   中英

Java通用列表<>

[英]Java Generic List<>

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

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;

但是,编译器只是说“ no”。

是否只有通过使用String.classfoo.getClass() java.util.List动态的泛型类型<T>

...

我实际上想做的是通过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;
    }
}

欢迎进行建设性的批评。 谢谢!

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

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

..也不工作!

List<String> list;

..作品,当然。

那么StringString.class之间的区别是什么?

或者有没有办法像这样设置值:

public enum EntityTypeEnum {
    ARTICLE(Article)
..

你是误会什么Java泛型有能力的:你不能这样做基于变量的的东西,只与变量的类型

基本上,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);

当然,您无法获得“真实”枚举的全部优点(例如序列化,抵抗反射攻击等)。 但是您会得到其他有用的信息,因此请权衡一下您的用例。

它不起作用,因为泛型是编译时概念,但是您尝试将其用作运行时概念。

区别在于,对于编译时概念,编译器需要能够根据代码中包含的信息(即,无需运行或评估)来确定类型。

此代码在语法上将是正确的:

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与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>();

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM