2008-12-16 38 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>>(); 
相關問題