java泛型类CastException

java泛型类CastException,java,generics,Java,Generics,抛出异常是因为类型“E”被读取为类对象,而不是指定的参数。应该是这样吗 @Override public E[] getAllEntities() { String jpdlQuery = String.format("select e from %s e", entityShortName); Query query = entityManager.createQuery(jpdlQuery, entityClass); return (E[]) query.getRe

抛出异常是因为类型“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[]getAllenties()
或类定义中的其他位置

然而,混合使用泛型和数组是一个非常糟糕的主意,因为数组在运行时有它们的基类型,而泛型则没有。您将从cast
(E[])
中获得编译警告

另外,您在
createQuery()
上遗漏了通用结果,它以您使用的形式返回
TypedQuery
。如果使用更具体的返回值,则不需要强制转换。此外,您不会返回原始的
列表
。不要使用原始类型


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

Collection
有两种
.toArray()
方法:

  • Object[]toArray()
    :此方法不接受任何参数,并返回一个运行时类始终为
    Object[]
    的数组。这是因为集合不知道在运行时它的组件类型是什么,并且没有任何参数,它也没有关于在运行时创建什么组件类型的数组的信息
  • T[]toArray(T[]a)
    :此方法接受数组参数,并返回与传入的数组具有相同运行时类的数组。它通过返回相同的数组对象,或者(如果传入的数组不够大)提取传入数组的运行时类的组件类型,并使用该类型创建相同运行时类的新数组对象来实现
  • 您使用了无参数的
    .toArray()
    方法;因此,它总是返回一个数组对象,其运行时类是
    object[]
    ,就像是由
    新对象[…]
    创建的一样。如果希望
    getAllenties()
    方法返回正确运行时类型的数组
    E[]
    ,那么它需要在运行时知道
    E
    是什么;为此,您需要让调用者传入类型为
    E[]
    Class
    的参数。比如说,

    public E[] getAllEntities(E[] array) {
        //...
        return query.getResultList().toArray(array);
    }
    
    另一种方法是返回一个
    列表
    ,运行时不需要知道它的组件类型,因此您可以创建一个
    列表
    ,而不需要知道运行时
    E
    是什么:

    public List<E> getAllEntities() {
        //...
        return query.getResultList();
    }
    
    公共列表getAllenties(){
    //...
    返回query.getResultList();
    }
    
    From:“返回数组的运行时组件类型为
    对象
    ”。除此之外,数组和泛型不能很好地混合;泛型会被类型擦除,但数组在运行时知道它们的组件类型。您应该将返回类型更改为
    List
    ,将
    query
    的类型声明为
    TypedQuery
    ,而不是
    query
    ,然后只需返回
    getResultList()的结果
    直接生成,而不是将其转换为数组。您可能只需要使用Spring Data JPA以类型安全和可测试的方式自动生成此代码。OP代码中的
    E
    可能来自类声明,将
    添加到方法中只会隐藏类的类型参数(可能会破坏某些东西). 此外,OP调用
    getResultList().toArray()
    ,因此它们不会尝试将
    List
    的大小写转换为
    E[]
    ,而是尝试将
    Object[]
    转换为
    E[]