Java 泛型类转换异常



引发异常是因为类型"E"被读取为类对象,而不是指定的参数。应该是这样吗?

@Override
public E[] getAllEntities() {
String jpdlQuery = String.format("select e from %s e", entityShortName);
Query query = entityManager.createQuery(jpdlQuery, entityClass);
return (E[]) query.getResultList().toArray();
}

你需要"泛型化"该方法,public <E> E[] getAllEntities()否则在类定义中的某个地方。

但是,混合泛型和数组是一个非常糟糕的主意,因为数组在运行时具有其基本类型,而泛型则没有。您将从强制转换(E[])收到编译警告。

此外,您省略了createQuery()上的通用结果,该结果在您使用的形式中返回一个TypedQuery<E>。如果使用更具体的返回值,则不需要强制转换。此外,您不会返回原始List。不要使用原始类型。

https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#createQuery-javax.persistence.criteria.CriteriaQuery- https://docs.oracle.com/javaee/7/api/javax/persistence/TypedQuery.html

数组在运行时知道其组件类型,因此在创建数组时,必须在运行时提供组件类型,使用不同组件类型创建的数组是不同运行时类的实例。另一方面,泛型类的实例在运行时不知道其泛型类型参数。

Collection有两种.toArray()方法:

  1. Object[] toArray():此方法不带任何参数,它返回一个运行时类始终为Object[]的数组。这是因为集合在运行时不知道它的组件类型是什么,并且没有任何参数,它没有关于在运行时要创建的数组组件类型的信息。
  2. <T> T[] toArray(T[] a):此方法接受一个数组参数,并返回一个与传入的运行时类相同的数组。它通过返回相同的数组对象或(如果传入的数组不够大(提取传入数组的运行时类的组件类型并使用它来创建相同运行时类的新数组对象来实现此目的。

你使用了不带参数的.toArray()方法;因此它将始终返回一个运行时类为Object[]的数组对象,就像由new Object[...]创建一样。如果您希望getAllEntities()方法返回正确运行时类型的数组E[],则需要在运行时以某种方式知道E是什么;为此,您需要让调用方传入类型E[]Class<E>的参数。例如

public E[] getAllEntities(E[] array) {
//...
return query.getResultList().toArray(array);
}

另一种方法是返回一个List,它在运行时不需要知道它的组件类型,因此您可以在不知道运行时E是什么的情况下创建一个List<E>

public List<E> getAllEntities() {
//...
return query.getResultList();
}

最新更新