简体   繁体   English

带有通用可变参数的 ClassCastException?

[英]ClassCastException with generic varargs?

I have a generic interface我有一个通用接口

{
void evaluate( TYPE... things );
}

I have a generic method with the signature我有一个带有签名的通用方法

<TYPE> void genericmethod( INTERFACE<TYPE> interfase, TYPE thing )
{
//the following line throws the ClassCastException
interfase.evaluate( thing );
}

PCard is a name in my project. PCard 是我项目中的一个名称。

So the call in the end is所以最后的电话是

INTERFACE<PCard> interfase = new WorkingImplementation<PCard>();
PCard pcard = new PCard();

this seems to throw a ClassCastException in the genericmethod, when it tries to call turn the single pcard into a varargs array.当它尝试调用将单个 pcard 转换为 varargs 数组时,这似乎在通用方法中抛出了 ClassCastException。

genericmethod( interfase, pcard );

The problem is relieved when there is no call to a genericmethod and you just call the interface directly.当没有调用泛型方法而您直接调用接口时,问题就得到了缓解。

interfase.evaluate( pcard );

What causes the Exception (internally)?是什么导致异常(内部)? (my personal guess is java is overwhelmed) (我个人的猜测是 java 不堪重负)

the Exception message:异常消息:

java.lang.ClassCastException: class [Ljava.lang.Object; java.lang.ClassCastException:class [Ljava.lang.Object; cannot be cast to class [Llib.cardgame.CG$PCard;不能转换为 class [Llib.cardgame.CG$PCard; ([Ljava.lang.Object; is in module java.base of loader 'bootstrap'; [Llib.cardgame.CG$PCard; is in unnamed module of loader 'app') ([Ljava.lang.Object;在加载程序'bootstrap'的模块java.base中;[Llib.cardgame.CG$PCard;在加载程序'app'的未命名模块中)

Short answer: Generics and arrays don't mix.简短回答: Generics 和 arrays 不能混用。 Use List<? extends TYPE> things使用List<? extends TYPE> things List<? extends TYPE> things instead. List<? extends TYPE> things

Generics are merely a compiler trick. Generics 只是一个编译器技巧。 They don't exist at runtime.它们在运行时不存在。 Arrays have a distinct type at runtime, like String[] or Number[] . Arrays 在运行时具有不同的类型,例如String[]Number[] But since a generic type doesn't exist at runtime, it's not possible for the compiler to generate code that will make an array of a generic type.但是由于在运行时不存在泛型类型,编译器不可能生成将生成泛型类型数组的代码。 (A call to a varargs method creates an array implicitly to hold the varargs arguments.) (对 varargs 方法的调用会隐式创建一个数组来保存 varargs arguments。)

In your case, the compiler emits a warning about this, and generates code that's as close to what you want as possible: the generated code for the implicit array that is created whenever a varargs method is called will be Object[] (since TYPE , I'm guessing, has no upper bound).在您的情况下,编译器会对此发出警告,并生成尽可能接近您想要的代码:每当调用 varargs 方法时创建的隐式数组的生成代码将是Object[] (因为TYPE ,我猜,没有上限)。

If you turn on all compiler warnings, you will be notified of this.如果您打开所有编译器警告,您将收到通知。 Addressing all compiler warnings properly (meaning, do not use @SuppressWarnings ) will guarantee that you won't get obscure surprises like the one you're getting now.正确解决所有编译器警告(意思是,不要使用@SuppressWarnings )将保证您不会像现在遇到的那样遇到令人费解的意外。

I recommend Gilad Bracha's generics tutorial .我推荐Gilad Bracha 的 generics 教程 I have found it invaluable for understanding how generics work.我发现它对于理解 generics 的工作原理非常宝贵。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM