我正在努力重构一些旧代码,我发现了一个片段,我不明白如何在Swing应用程序框架类TaskListener.Adapter
中正确使用Generics。
这是相关的代码段:
public void executeTask(Task<?, ?> task, boolean handleException) {
task.addTaskListener(new TaskListener.Adapter() { /* <-- Two warnings here */
@Override
public void failed(TaskEvent event) { /* ... */ }
});
getContext().getTaskService().execute(task);
}
1。首先,我想摆脱警告。 “未选中转化”和“找到原始类型”。我尝试将代码更改为new TaskListener.Adapter<Object, Object>
,但后来我得到错误“无法应用于给定类型”。由于(Task<?, ?>
声明,我可以在这里使用原始类型吗?
2。 failed
中org.jdesktop.application.TaskListener.Adapter
方法的声明为public void failed(TaskEvent<Throwable> event)
,但如果我尝试将代码更改为此:
@Override
public void failed(TaskEvent<Throwable> event) { /* ... */ }
我得“方法不会覆盖超类型的方法”。我必须再次使用原始TaskEvent
。那是为什么?
感谢您的帮助。
编辑:Jarvana上的TaskListener的Javadoc。
答案 0 :(得分:2)
您无法将<Object, Object>
通用的适配器应用于Task<?, ?>
,因为谁知道通配符是什么?它可能是Task<String, Integer>
,在这种情况下,适配器的边界将不匹配,因此它不适用。
(好吧,在这种情况下,它们可能是好的,因为它们是消费者,但编译器无法自己推断。如果 的话,那么{{1需要声明采用Task.addTaskListener
以满足编译器。)
由于声明TaskListener<? super T, ? super V>
的方式,您需要传入一个具有完全相同的通用边界的侦听器。当你将它们声明为通配符时,这是不可能的,因为你以后无法再引用它们。你需要做的是使方法通用,这类似于使用addTaskListener
通配符,除非你给它们命名,以便稍后可以在方法中引用它们:
?
至于第二部分,我不知道 - 它对我来说也很好。也许这是来自原始类型的一些误导性错误,尽管这似乎不太可能,因为声明中根本不涉及泛型参数。如果编译器在上述更改后仍然不喜欢覆盖,那么问题可能就在其他地方(就像你不小心把方法放在了错误的类'范围等)。
答案 1 :(得分:1)
您是否尝试过new TaskListener.Adapter<?, ?>
?
当您尝试添加<Throwable>
类型参数时,您的new TaskListener.Adapter
是作为原始类型创建的,还是具有泛型类型参数?
在第一种情况下,发生的情况是编译器将整个类(及其超类)视为原始类型(为了向后兼容)。也就是说,类中的所有泛型类型参数,,无论是否是类或特定于方法的,都被省略。因此,当它使用泛型参数找到方法声明时,会将其与超类方法与 raw 参数进行比较。因此,没有匹配。
答案 2 :(得分:1)
不知道库和源代码,这是我的猜测:
public <K, V> void executeTask(final Task<K, V> task, boolean handleException) {
task.addTaskListener(new TaskListener.Adapter<K, V>() {
@Override
public void failed(final TaskEvent<Throwable> event) {
super.failed(event);
}
});
getContext().getTaskService().execute(task);
}
(编辑:我下载了lib并且上面的代码在没有警告的情况下编译)