我有一个使用泛型的简单类。
public class ResponseWorkerRunnable<Parameter, Result> implements Runnable {
private final ResponseWorker<Parameter, Result> worker;
/**
* The parameters for {@link ResponseWorker#doInBackground(Object...)}
*/
private final Parameter[] params;
public ResponseWorkerRunnable(ResponseWorker<Parameter, Result> worker,
Parameter... params) {
uiThreadHandler = new Handler(Looper.getMainLooper());
this.worker = worker;
this.params = params;
}
@Override
public void run() {
try {
Result res = worker.doInBackground(params);
postResultBack(res);
} catch (Exception e) {
postErrorBack(e);
}
}
}
和我的 ResponseWorker:
public interface ResponseWorker<Parameter, Result> {
public Result doInBackground(Parameter... param) throws Exception;
}
问题是,我得到了 ClassCastException:
java.lang.ClassCastException: java.lang.Object[] cannot be cast to model.Table[]
我做了这样的事情:
Table t = new Table();
ResponseWorker<Table, SuperTable> worker = ... ;
ResponseWorkerRunnable<Table, SuperTable> r = new ResponseWorkerRunnable<Table, SuperTable>(worker, t);
然后 ResponseWorkerRunnable 将被调度并在将来运行,但出现此异常:
java.lang.ClassCastException: java.lang.Object[] cannot be cast to model.Table[]
在 ResponseWorkerRunnable run() 方法中的这一行:
Result res = worker.doInBackground(params);
我已使用调试器检查 Parameter[] params 字段(在 ResponseWorkerRunnable 中)并将其设置为 Object[1]{Table@4237c0e0}
所以它是一个对象数组,但 ResponseWorker.doInBackground 需要一个 Table 类的数组。
如何正确转换?
Result res = worker.doInBackground((Parameter[]) params);
还有其他想法或暗示可能出现什么问题吗?
------更新------
我使用一个名为 ResponseWorkerExecutor 的单例类将 ResponseWorkerRunnable (带有线程池)调度到
class ResponseWorkerExecutor {
public static <Parameter, Result> Future<?> submit(
ResponseWorker<Parameter, Result> responseWorker, Parameter ... params) {
return INSTANCE.executor
.submit(new ResponseWorkerRunnable<Parameter, Result>(
responseWorker, params));
}
}
所以在我的代码中我做了这样的事情: 我做了这样的事情:
Table t = new Table();
// ResponseWorker implementation
ResponseWorker<Table, SuperTable> worker = ... ;
// Here is the problem with the args
ResponseWorkerExecutor.submit(worker, t);
最佳答案
由于泛型在 Java 中的工作方式(请阅读此处有关 type erasure 的信息),实际的 Parameter
类在生成的字节码中被 Object
替换,这就是为什么您的 varargs 数组是 Object[]
而不是 Table[]
。
在这种情况下有一个解决方法应该可行,它涉及对您的代码进行一些更改:
// Pass the actual class object to your Runnable, in this case t.getClass() -> Table.class
ResponseWorkerRunnable<Table, SuperTable> r = new ResponseWorkerRunnable<Table, SuperTable>(worker, t, t.getClass());
然后:
public class ResponseWorkerRunnable<Parameter, Result> implements Runnable {
private final ResponseWorker<Parameter, Result> worker;
/**
* The parameters for {@link ResponseWorker#doInBackground(Object...)}
*/
private final Parameter[] params;
private final Class<?> actualClass;
public ResponseWorkerRunnable(ResponseWorker<Parameter, Result> worker, Parameter... params, Class<?> actualClass) {
uiThreadHandler = new Handler(Looper.getMainLooper());
this.worker = worker;
this.params = params;
this.actualClass = actualClass;
}
@Override
public void run() {
try {
Result res = worker.doInBackground((Parameter[]) Arrays.copyOf(params, params.length, actualClass));
postResultBack(res);
} catch (Exception e) {
postErrorBack(e);
}
}
}
它的作用是获取Object[]
并将其内容复制到一个新的、真实的Parameter[]
中,无论实际的类Parameter
是什么> 指的是。然后它使用这个新数组进行可变参数调用。
关于java - 泛型:ClassCastException:java.lang.Object[] 无法转换为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20244957/