2008-12-16 16 views
8

Je ne comprends pas pourquoi ce code ne compilera pasinvokeAll() ne sont pas prêts à accepter une 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); 

Le msg d'erreur est:

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

list est un Collection de DocFeeder, qui met en œuvre Callable<Boolean> - Que se passe-t-il ?!

Répondre

18

Juste pour développer un peu la réponse de saua ...

En Java 5, la méthode a été déclarée comme:

invokeAll(Collection<Callable<T>> tasks) 

En Java 6, la méthode est déclarée comme:

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

La différence de wildcarding est très important - parce que List<DocFeeder>est un Collection<? extends Callable<T>> mais c'est pas un Collection<Callable<T>>. Ce qui se passerait avec cette méthode:

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

C'est légal - mais il est clairement mal si vous pouvez appeler addSomething avec un List<DocFeeder> car il va essayer d'ajouter un non-DocFeeder à la liste. Par conséquent, si vous êtes bloqué avec Java 5, vous devez créer un List<Callable<Boolean>> à partir de votre List<DocFeeder>.

7

Ce code se compile parfaitement bien avec Java 6, mais ne parvient pas à compiler avec Java 5 donnant

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

Cependant changer le list comme ceci:

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

fait fonctionner à la fois sur Java 5 et Java 6.

0

Merci pour la réponse détaillée, mais il me bugs encore - Callable est une interface, alors en fait, la fonction "addSomething" dans la réponse de Jon devrait être OK (non seulement légal, mais raisonnable) - parce que, bien, c'est la point entier des interfaces - Tant que vous respectez un accord initial, je ne m'inquiète pas de l'objet que vous ajouteriez à la liste. En fait, le problème que vous avez présenté devrait être abordé sous un autre angle.

En outre, le fait reste que le code ne compile pas - et il devrait avoir ...

+0

Non, il ne doit pas * * ont compilé (Java contre 5) - à cause de cela problème de variance Fondamentalement, la variance dans les génériques ne fonctionne pas comme vous le souhaitez, et ne devrait pas - ce serait dangereux. –

+0

(Bien sûr, ils auraient dû déclarer la méthode dans Java 5 comme ils l'ont fait dans Java 6 - le correctif appliqué est tout à fait approprié.) –

+1

Le correctif est inapproprié car cela signifie que vous ne pouvez pas écrire correctement un ExecutorService pour les deux. et 1.6. (jsr166_ s'est excusé pour les deux cockups. –

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