问题
I fail to understand why this code won't compile
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 error msg is:
The method invokeAll(Collection<Callable<T>>) in the type ExecutorService is
not applicable for the arguments (List<DocFeeder>)
list is a Collection of DocFeeder, which implements Callable<Boolean> - What is going on?!
回答1:
Just to expand on saua's answer a little...
In Java 5, the method was declared as:
invokeAll(Collection<Callable<T>> tasks)
In Java 6, the method is declared as:
invokeAll(Collection<? extends Callable<T>> tasks)
The wildcarding difference is very important - because List<DocFeeder> is a Collection<? extends Callable<T>> but it's not a Collection<Callable<T>>. Consider what would happen with this method:
public void addSomething(Collection<Callable<Boolean>> collection)
{
collection.add(new SomeCallable<Boolean>());
}
That's legal - but it's clearly bad if you can call addSomething with a List<DocFeeder> as it will try to add a non-DocFeeder to the list.
So, if you are stuck with Java 5, you need to create a List<Callable<Boolean>> from your List<DocFeeder>.
回答2:
That code compiles perfectly fine with Java 6, but fails to compile with Java 5 giving
Foo.java:9: cannot find symbol
symbol : method invokeAll(java.util.List)
location: interface java.util.concurrent.ExecutorService
executor.invokeAll(list);
^
1 error
However changing the list like this:
Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>();
Makes it work on both Java 5 and Java 6.
回答3:
Thanks for the detailed answer , but it still bugs me - Callable is an interface , so actually , the "addSomething" function in Jon's answer should be OK (not only legal , but reasonable) - because , well , that's the whole point of interfaces - As long as you comply with some initial agreement , I don't care which object you'd add to the list. imo , the problem you presented should be addressed on a different scope.
Besides that , the fact remains that the code didn't compile - and it should have...
回答4:
Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>();
来源:https://stackoverflow.com/questions/370707/invokeall-is-not-willing-to-accept-a-collectioncallablet