2

我目前正在重构一些旧代码,我发现了一个片段,我不明白如何为 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.Adapterpublic void failed(TaskEvent<Throwable> event),但是如果我尝试将我的代码更改为:

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

我得到“方法不会覆盖超类型中的方法”。我必须再次使用 raw TaskEvent。这是为什么?

感谢您的帮助。

编辑: Javadoc for TaskListener on Jarvana

4

3 回答 3

2

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

(好吧,在这种情况下,它们可能是可以的,因为它们是消费者,但编译器无法自行推断。如果这种情况,则Task.addTaskListener需要声明为 aTaskListener<? 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);
}

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

于 2011-08-11T08:39:37.540 回答
1
  1. 你试过new TaskListener.Adapter<?, ?>吗?

  2. 当您尝试添加<Throwable>类型参数时,您new TaskListener.Adapter是作为原始类型创建的,还是具有泛型类型参数?

    在第一种情况下,编译器将整个类(及其超类)视为原始类型(为了向后兼容)。也就是说,类中的所有泛型类型参数,无论它们是类特定的还是方法特定的,都将被省略。因此,当它找到带有泛型参数的方法声明时,会将其与带有原始参数的超类方法进行比较。因此,没有匹配。

于 2011-08-11T08:34:17.837 回答
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,上面的代码编译没有警告)

于 2011-08-11T08:39:13.870 回答