2008-12-16 43 views
8

我不明白为什么这个代码不会编译的invokeAll()是不是愿意接受一个Collection <Callable<T>>

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是的CollectionDocFeeder,它实现Callable<Boolean> - 发生了什么?

回答

18

只是为了扩大绍阿的答案有点...

在Java 5中,在声明的方法为:

invokeAll(Collection<Callable<T>> tasks) 

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

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

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

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

这是合法的 - 但它显然是不好的,如果你可以调用addSomethingList<DocFeeder>,因为它会尝试在非DocFeeder添加到列表中。

因此,如果您遇到Java 5,您需要从List<DocFeeder>创建一个List<Callable<Boolean>>

7

该代码编译的Java 6完全正常,但无法使用Java 5编译给人

Foo.java:9: cannot find symbol 
symbol : method invokeAll(java.util.List) 
location: interface java.util.concurrent.ExecutorService 
executor.invokeAll(list); 
     ^
1 error

但是改变list这样的:

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

使得双方的Java 5和工作Java 6.

0

感谢您的详细回答,但它还是我的错误 - 可赎回是一个接口,所以实际上,在Jon的回答“addSomething”功能应该是OK(不仅是合法的,但合理的) - 因为,这就是整个接口点 - 只要你遵守一些初步的协议,我不在乎你要添加到列表中的哪个对象。您提出的问题应该在不同的范围内解决。

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

+0

不,*不应*编译(在Java 5) - 正因为如此非常变异的问题。基本上泛型的变化不会按照您期望的方式工作,也不应该 - 这会很危险。 – 2008-12-16 09:45:59

0
Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>(); 
相关问题