我目前正在重构一些旧代码,并且发现了一个片段,在该片段中我不理解如何为Swing应用程序框架类TaskListener.Adapter
正确使用泛型。
这是相关的代码片段:
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。
最佳答案
您不能将通用化为<Object, Object>
的适配器应用于Task<?, ?>
,因为谁知道通配符是什么?可能是Task<String, Integer>
,在这种情况下适配器的边界不匹配,因此将不适用。
(好吧,在这种情况下可能是可以的,因为它们是使用者,但编译器无法自行推断出这种情况。如果是这种情况,则需要声明Task.addTaskListener
以采用TaskListener<? super T, ? super V>
为了使编译器满意。)
由于addTaskListener
的声明方式,您需要传入具有完全相同的通用范围的侦听器。当您将它们声明为通配符时,这是不可能的,因为您以后无法引用它们。您需要做的是使方法通用,这与使用?
通配符相似,不同之处在于您为它们指定了名称,以便稍后可以在方法中引用它们:
public <T, V> void executeTask(Task<T, V> task, boolean handleException) {
task.addTaskListener(new TaskListener.Adapter<T, V>() {
@Override
public void failed(TaskEvent event) { /* ... */ }
});
getContext().getTaskService().execute(task);
}
至于第二部分,我不知道-对我来说也很好。也许这是来自原始类型的一些误导性错误,尽管由于根本没有任何通用参数涉及到声明,所以这似乎不太可能。如果在完成上述更改后编译器仍然不喜欢覆盖,则问题可能出在其他地方(例如您不小心将方法放置在错误的类的范围内,等等)。