2008-12-16 14 views
8

no entiendo por qué este código no se compilaráinvokeAll() no está dispuesto a aceptar una colección <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); 

El msg de error es:

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

list es una de CollectionDocFeeder, que implementa Callable<Boolean> - ¿Qué está pasando ?!

Respuesta

18

Solo para expandir la respuesta de saua un poco ...

En Java 5, el método fue declarado como:

invokeAll(Collection<Callable<T>> tasks) 

En Java 6, se declara el método como:

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

La diferencia comodín es muy importante - porque List<DocFeeder>es un Collection<? extends Callable<T>> pero es no a Collection<Callable<T>>. Considere lo que sucedería con este método:

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

Eso es legal - pero está claro que es malo si se puede llamar addSomething con un List<DocFeeder> ya que se trata de añadir un no DocFeeder a la lista.

Por lo tanto, si está atascado con Java 5, necesita crear un List<Callable<Boolean>> desde su List<DocFeeder>.

7

Ese código se compila perfectamente bien con Java 6, pero falla al compilar con Java 5 dando

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

Sin embargo el cambio de la list así:

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

hace que funcione tanto en Java 5 y Java 6.

0

Gracias por la respuesta detallada, pero todavía me molesta - Callable es una interfaz, así que, en realidad, la función "addSomething" en la respuesta de Jon debería ser correcta (no solo legal, sino razonable) porque, bueno, esa es la punto completo de las interfaces: siempre que cumpla con algún acuerdo inicial, no me importa qué objeto agregaría a la lista. imo, el problema que presenta debe abordarse en un ámbito diferente.

Además de eso, el hecho es que el código no se compilará - y debe tener ...

+0

No, no debería * * han compilado (en contra de Java 5) - debido a eso muy problema de varianza Básicamente, la varianza en los genéricos no funciona de la forma en que lo esperaba, y no debería serlo, sería peligroso. –

+0

(Por supuesto, deberían haber declarado el método en Java 5 de la forma en que lo hicieron en Java 6 - la corrección aplicada allí es completamente apropiada.) –

+1

La corrección es inapropiada porque significa que no puede escribir limpiamente un ExecutorService para ambos 1.5 y 1.6. (jsr166_ se disculpó por ambos cockups.) –

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