Java:是否可以将参数化类型用于另一个参数化类型?

时间:2014-05-04 22:11:19

标签: java generics jpa type-conversion

不确定如何标题这个问题,但会尝试解释。我正在尝试使用JPA标准API并遇到一些问题;

我有以下实体;

public class Sword extends Item {}
public class InventoryItem<T extends Item> {}

这就是我正在努力工作(除非它返回List<InventoryItem>但我希望它返回List<InventoryItem<Sword>>),否则不会编译:

public List<InventoryItem<Sword>> get() {
  CriteriaBuilder cb = entityManager.getCriteriaBuilder();
  CriteriaQuery<InventoryItem> cq = cb.createQuery(InventoryItem.class);
  Root<InventoryItem> o = cq.from(InventoryItem.class);
  .........
  List<InventoryItem> resultList = query.getResultList();
  return resultList; 
}

我尝试了以下内容;

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<InventoryItem<Sword>> cq = cb.createQuery(InventoryItem<Sword>.class);
    Root<InventoryItem<Sword>> o = cq.from(InventoryItem<Sword>.class);

但是会出现以下错误;

无法将InventoryItem解析为变量。

无法将剑解析为变量。

1 个答案:

答案 0 :(得分:0)

InventoryItem<Sword>.class是Java中的非法表达。您不能将泛型应用于类文字;即使你可以,泛型也会在编译时被删除,同时返回相同的Class对象。

要说服编译器将您的类文字视为通用表达式,您需要将其强制转换:

CriteriaQuery<InventoryItem<Sword>> cq =
    cb.createQuery((Class) InventoryItem.class);
Root<InventoryItem<Sword>> o = cq.from((Class) InventoryItem.class);

CriteriaQuery<InventoryItem<Sword>> cq =
    (CriteriaQuery) cb.createQuery(InventoryItem.class);
Root<InventoryItem<Sword>> o =
    (Root) cq.from(InventoryItem.class);

...虽然我还没有在本地对这些进行测试,但是他们需要使用@SuppressWarnings({"unchecked", "rawtypes"}),因为Java不能保证没有仿制品的演员的安全:你正在服用在这里打字安全。

(注意:这就是为什么像Guava和Guice这样的库分别引入了TypeTokenTypeLiteral这样的概念,以体现具有泛型类型的类文字。)