如果我使用以下代码,则会出现ClassCastException,即使我根本没有使用强制转换。
更奇怪的是,如果在Android(dalvik)上运行此代码,则异常中不包括堆栈跟踪,如果将接口更改为抽象类,则异常变量“e”为空。
代码:
public class GenericsTest {
public class Task<T> {
public void doStuff(T param, Callback<T> callback) {
// This gets called, param is String "importantStuff"
// Working workaround:
//T[] arr = (T[]) Array.newInstance(param.getClass(), 1);
//arr[0] = param;
//callback.stuffDone(arr);
// WARNING: Type safety: A generic array of T is created for a varargs parameter
callback.stuffDone(param);
}
}
public interface Callback<T> {
// WARNING: Type safety: Potential heap pollution via varargs parameter params
public void stuffDone(T... params);
}
public void run() {
Task<String> task = new Task<String>();
try {
task.doStuff("importantStuff", new Callback<String>() {
public void stuffDone(String... params) {
// This never gets called
System.out.println(params);
}});
} catch (ClassCastException e) {
// e contains "java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;"
System.out.println(e.toString());
}
}
public static void main(String[] args) {
new GenericsTest().run();
}
}
如果运行这段代码,你会遇到一个
ClassCastException
错误,提示无法将Object
转换为String
,并且堆栈跟踪指向无效的行号。这是Java的一个bug吗?我已经在Java 7和Android API 8中进行了测试。我对此进行了处理(在doStuff
方法中用注释掉的方式),但是这么做似乎有点愚蠢。如果我去掉可变参数(T...
),一切都能正常工作,但我的实际实现需要它。异常的堆栈跟踪如下:
java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
at GenericsTest$1.stuffDone(GenericsTest.java:1)
at GenericsTest$Task.doStuff(GenericsTest.java:14)
at GenericsTest.run(GenericsTest.java:26)
at GenericsTest.main(GenericsTest.java:39)