ClassCastException while using varargs and generics

我与影子孤独终老i 提交于 2019-12-01 19:20:33

This is expected behaviour. When you use generics in Java, the actual types of the objects are not included in the compiled bytecode (this is known as type erasure). All types become Object and casts are inserted into the compiled code to simulate typed behaviour.

Additionally, varargs become arrays, and when a generic varargs method is called, Java creates an array of type Object[] with the method parameters before calling it.

Thus, your line callback.stuffDone(param); compiles as callback.stuffDone(new Object[] { param });. However, your implementation of the callback requires an array of type String[]. The Java compiler has inserted an invisible cast in your code to enforce this typing, and because Object[] cannot be cast to String[], you get an exception. The bogus line number you see is presumably because the cast doesn't appear anywhere in your code.

One workaround for this is to completely remove the generics from your Callback interface and class, replacing all types with Object.

grahamparks answer is correct. The mysterious typecast is normal behaviour. They are inserted by the compiler to ensure that the application is runtime typesafe in the face of possible incorrect use of generics.

If you are playing by the rules, this typecast will always succeed. It is failing because you have ignored / suppressed the warnings about unsafe use of generics. This is not a wise thing to do ... especially if you don't understand exactly understand what they mean, and whether they can be safely ignored.

That's indeed due to type erasure, but the critical part here is varargs. They are, as already noted, implemented as table. So compiler is actually creating an Object[] to pack your params and hence later invalid cast. But there is a hack around it: if you're nice enough to pass a table as vararg, compiler will recognize it, not re-pack it and because you saved him some work it will let you run your code :-)

Try to run after following modifications:

public void doStuff(T[] param, Callback callback) {

and

task.doStuff(new String[]{"importantStuff"}, new Callback() {

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!