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

标签 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 无法解析为变量。

Sword 无法解析为变量。

最佳答案

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 这样的概念,来体现具有泛型类型的类文字。)

关于Java:是否可以将一个参数化类型用于另一个参数化类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23462163/

相关文章:

java - 将 JPA query.getResultList() 转换为我的对象

java - 为什么不可变对象(immutable对象)允许遵守里氏替换原则?

Java计算器 - 调车场

java - 数组向右移动,但索引 [0] 消失了

java - 为什么 G1 收集器在对象复制上花费这么多时间

generics - 为什么以下通用约束会产生编译器错误?

java - jpa 持久保存具有两个所有者的同一对象

java - 参数化原始类型

java - 通用工厂模式-如何处理返回类型

java - Spring Data错误由: org. hibernate.QueryException引起:无法解析属性