我有一个通用接口
{
void evaluate( TYPE... things );
}
我有一个带有签名的通用方法
<TYPE> void genericmethod( INTERFACE<TYPE> interfase, TYPE thing )
{
//the following line throws the ClassCastException
interfase.evaluate( thing );
}
PCard是我项目中的名字。
所以最后的电话是
INTERFACE<PCard> interfase = new WorkingImplementation<PCard>();
PCard pcard = new PCard();
这似乎在泛型方法中引发ClassCastException,当它尝试调用时将单个pcard转换为varargs数组。
genericmethod( interfase, pcard );
当不调用泛型方法而您直接调用接口时,该问题得到缓解。
interfase.evaluate( pcard );
是什么原因(内部)导致异常? (我个人的猜测是Java不堪重负)
异常消息:
java.lang.ClassCastException:类[Ljava.lang.Object;不能转换为类[Llib.cardgame.CG $ PCard; ([Ljava.lang.Object;位于加载程序'bootstrap'的模块java.base中; [Llib.cardgame.CG $ PCard;位于加载程序'app'的未命名模块中)
答案 0 :(得分:1)
简短的回答:泛型和数组不能混合使用。请改用List<? extends TYPE> things
。
泛型仅仅是编译器的把戏。它们在运行时不存在。数组在运行时具有不同的类型,例如String[]
或Number[]
。但是,由于在运行时不存在泛型类型,因此编译器无法生成将生成泛型类型的数组的代码。 (对varargs方法的调用会隐式创建一个数组来保存varargs参数。)
在您的情况下,编译器会对此发出警告,并生成与您想要的代码尽可能接近的代码:每当调用varargs方法时,为隐式数组生成的代码将为{{1} }(自Object[]
起,我猜没有上限)。
如果打开所有编译器警告,则会收到通知。正确解决所有编译器警告(即,不要使用TYPE
)将确保您不会像现在看到的那样获得令人惊讶的惊喜。
我推荐Gilad Bracha’s generics tutorial。我发现它对于了解泛型的工作原理非常重要。