7

我不明白为什么这段代码无法编译

ExecutorService executor = new ScheduledThreadPoolExecutor(threads);

class DocFeeder implements Callable<Boolean> {....} 
... 
List<DocFeeder> list = new LinkedList<DocFeeder>();
list.add(new DocFeeder(1));
...
executor.invokeAll(list);

错误消息是:

The method invokeAll(Collection<Callable<T>>) in the type ExecutorService is 
not applicable for the arguments (List<DocFeeder>)  

list是一个Collectionof DocFeeder,它实现了Callable<Boolean>- 这是怎么回事?!

4

4 回答 4

18

只是为了稍微扩展一下saua的答案......

在 Java 5 中,该方法被声明为:

invokeAll(Collection<Callable<T>> tasks) 

在 Java 6 中,该方法被声明为:

invokeAll(Collection<? extends Callable<T>> tasks) 

通配符的区别非常重要 - 因为List<DocFeeder> aCollection<? extends Callable<T>>但它不是a Collection<Callable<T>>。考虑使用这种方法会发生什么:

public void addSomething(Collection<Callable<Boolean>> collection)
{
    collection.add(new SomeCallable<Boolean>());
}

这是合法的 - 但如果你可以addSomething用 a调用它显然很糟糕,List<DocFeeder>因为它会尝试将非 DocFeeder 添加到列表中。

因此,如果您坚持使用 Java 5,则需要List<Callable<Boolean>>从您的List<DocFeeder>.

于 2008-12-16T08:55:35.287 回答
7

该代码使用 Java 6 编译得非常好,但无法使用 Java 5 编译

Foo.java:9:找不到符号
符号:方法 invokeAll(java.util.List)
位置:接口 java.util.concurrent.ExecutorService
executor.invokeAll(list);
        ^
1 个错误

然而改变list这样的:

Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>();

使其适用于 Java 5 和 Java 6。

于 2008-12-16T08:42:58.807 回答
0

感谢您提供详细的答案,但它仍然困扰着我-Callable 是一个接口,所以实际上,Jon 的答案中的“addSomething”函数应该没问题(不仅合法,而且合理)-因为,嗯,这就是接口的全部意义- 只要您遵守一些初步协议,我不在乎您将哪个对象添加到列表中。imo,您提出的问题应该在不同的范围内解决。

除此之外,事实仍然是代码没有编译 - 它应该......

于 2008-12-16T09:03:47.517 回答
0
Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>();
于 2009-04-16T03:56:14.210 回答