我无法理解为什么这段代码无法编译
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
是Collection
的{{1}},它实现DocFeeder
- 发生了什么?!
答案 0 :(得分:18)
稍微扩展一下saua的答案......
在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>());
}
这是合法的 - 但如果您可以使用addSomething
致电List<DocFeeder>
,那将是非常糟糕的,因为它会尝试将非DocFeeder添加到列表中。
因此,如果您遇到Java 5,则需要从List<Callable<Boolean>>
创建List<DocFeeder>
。
答案 1 :(得分: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.
答案 2 :(得分:0)
感谢您的详细解答,但它仍然让我感到烦恼 - Callable是一个界面,所以实际上,Jon的答案中的“addSomething”功能应该没问题(不仅合法,而且合理) - 因为,那就是整个接口点 - 只要你遵守一些初始协议,我就不关心你要添加到列表中的对象。 imo,你提出的问题应该在不同的范围内解决。
除此之外,事实仍然是代码没有编译 - 它应该有......
答案 3 :(得分:0)
Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>();