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 - это Collection от DocFeeder, который реализует Callable<Boolean> - Что происходит ?!

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
7
0
9 343
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Этот код отлично компилируется с 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.

Ответ принят как подходящий

Просто чтобы немного расширить ответ saua ...

В Java 5 метод был объявлен как:

invokeAll(Collection<Callable<T>> tasks) 

В Java 6 метод объявлен как:

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

Различие в подстановочных знаках очень важно - потому что List<DocFeeder>является - это Collection<? extends Callable<T>>, а нет - это 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>.

Спасибо за подробный ответ, но это все еще меня беспокоит - Callable - это интерфейс, поэтому на самом деле функция addSomething в ответе Джона должна быть в порядке (не только законной, но и разумной) - потому что, ну, в этом вся суть интерфейсов - Пока вы соблюдаете какое-то первоначальное соглашение, мне все равно, какой объект вы добавите в список. imo, проблема, которую вы представили, должна рассматриваться в другом контексте.

Кроме того, факт остается фактом: код не компилировался - и он должен был иметь ...

Нет, это не должен скомпилировано (против Java 5) - из-за той самой проблемы с дисперсией. По сути, вариативность в дженериках работает не так, как вы ожидаете, и не должна - это было бы опасно.

Jon Skeet 16.12.2008 12:45

(Конечно, они должны были объявить метод в Java 5, как они это сделали в Java 6 - исправление, примененное там, вполне уместно.)

Jon Skeet 16.12.2008 12:46

Исправление неуместно, потому что это означает, что вы не можете чисто написать ExecutorService как для 1.5, так и для 1.6. (jsr166_ извинился за оба коктейля.)

Tom Hawtin - tackline 16.12.2008 17:17

@Tom: Это правда, но я бы предпочел исправление, совместимое на стороне клиента, потому что определенно больше людей используют ExecutorService, чем тех, кто его пишет.

Joachim Sauer 17.12.2008 11:17
Collection<Callable<Boolean>> list = new LinkedList<Callable<Boolean>>();

Другие вопросы по теме