不确定如何为该问题加上标题,但会尝试进行解释。我正在尝试使用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无法解析为变量。

剑无法解析为变量。

最佳答案

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之类的概念,以使类文字具有通用类型的原因。)

09-26 14:23