了解TaskListener的泛型类型参数

时间:2011-08-11 08:05:44

标签: java generics swing-app-framework jsr296

我正在努力重构一些旧代码,我发现了一个片段,我不明白如何在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。 failedorg.jdesktop.application.TaskListener.Adapter方法的声明为public void failed(TaskEvent<Throwable> event),但如果我尝试将代码更改为此:

@Override
public void failed(TaskEvent<Throwable> event) { /* ... */ }

我得“方法不会覆盖超类型的方法”。我必须再次使用原始TaskEvent。那是为什么?

感谢您的帮助。

编辑Jarvana上的TaskListener的Javadoc。

3 个答案:

答案 0 :(得分:2)

您无法将<Object, Object>通用的适配器应用于Task<?, ?>,因为谁知道通配符是什么?它可能是Task<String, Integer>,在这种情况下,适配器的边界将不匹配,因此它不适用。

(好吧,在这种情况下,它们可能是好的,因为它们是消费者,但编译器无法自己推断。如果 的话,那么{{1需要声明采用Task.addTaskListener以满足编译器。)

由于声明TaskListener<? super T, ? super V>的方式,您需要传入一个具有完全相同的通用边界的侦听器。当你将它们声明为通配符时,这是不可能的,因为你以后无法再引用它们。你需要做的是使方法通用,这类似于使用addTaskListener通配符,除非你给它们命名,以便稍后可以在方法中引用它们:

?

至于第二部分,我不知道 - 它对我来说也很好。也许这是来自原始类型的一些误导性错误,尽管这似乎不太可能,因为声明中根本不涉及泛型参数。如果编译器在上述更改后仍然不喜欢覆盖,那么问题可能就在其他地方(就像你不小心把方法放在了错误的类'范围等)。

答案 1 :(得分:1)

  1. 您是否尝试过new TaskListener.Adapter<?, ?>

  2. 当您尝试添加<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并且上面的代码在没有警告的情况下编译)