可调用和泛型的集合

用户名

我需要在并发线程中启动一堆任务并检索其结果。

这是我的代码:

List<Callable<? extends Object>> tasks = new ArrayList<>();

// Adding some tasks whith return different types of results:
// Callable<Double>, Callable<String>, Callable<SomeOtherType>, and so on...

List<Future<? extends Object>> results = executor.invokeAll( tasks );

但是IDE向我显示了下一个错误:

no suitable method found for invokeAll(List<Callable<? extends Object>>)

    method ExecutorService.<T#1>invokeAll(Collection<? extends Callable<T#1>>)
            is not applicable
      (cannot infer type-variable(s) T#1
        (argument mismatch; List<Callable<? extends Object>> cannot be converted
                to Collection<? extends Callable<T#1>>

    method ExecutorService.<T#2>invokeAll(Collection<? extends Callable<T#2>>,long,TimeUnit)
            is not applicable
      (cannot infer type-variable(s) T#2
        (actual and formal argument lists differ in length))

  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method
            <T#1>invokeAll(Collection<? extends Callable<T#1>>)
    T#2 extends Object declared in method
            <T#2>invokeAll(Collection<? extends Callable<T#2>>,long,TimeUnit)

方法签名为:

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

显然,我可以替换<? extends Object><Object>,并返回所有任务Object(例如,替换SomeTask1 implements Callable<Double>SomeTask1 implements Callable<Object>)。

但是我的问题是:为什么会发生此错误?我不明白为什么我不能这样编码。谁能说清楚?

值得
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)

这表示存在一个类型变量T,使得参数为Collection<? extends Callable<T>>即,此方法签名假定列表中的所有Callables具有相同的type参数。您的列表不是这种情况,这就是编译器拒绝您的代码的原因。

api方法应该声明如下:

<T> List<Future<? extends T>> invokeAll(Collection<? extends Callable<? extends T>> tasks);

在Java中设计通用API时,这是一个众所周知的陷阱。缺少声明站点协方差(这将允许声明状态Callable<String>为的子类型Callable<Object>)要求在通用类型的每次使用时都使用通配符类型指定协方差。也就是说,API永远不要编写Callable<T>,而应该始终编写Callable<? extends T>当然,如本例所示,这是多余的并且容易忘记。

在您的特定情况下,最好这样做:

List<Future<?>> futures = new ArrayList<>();
for (Callable<?> callable : tasks) {
     futures.add(executor.submit(callable));
}
for (Future<?> future : futures) {
    future.get();
}

如果您不止一次需要这样做,可以将其放入实用程序方法中,并牢记使用适当的签名;-)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

Java泛型和集合的问题

来自分类Dev

泛型类型,集合和对象引用

来自分类Dev

泛型类型集合

来自分类Dev

C#创建包含泛型集合的泛型方法并调用Sum()

来自分类Dev

谁能举例说明如何在Java的InvokeAll()可调用方法中使用泛型?

来自分类Dev

从泛型类调用泛型EventHandler

来自分类Dev

泛型-集合中的Java集合

来自分类Dev

Autofac和泛型

来自分类Dev

泛型和继承?

来自分类Dev

功能和泛型

来自分类Dev

泛型和ClassCastException

来自分类Dev

泛型和Ormlite

来自分类Dev

ThreadLocal和泛型

来自分类Dev

泛型和指针

来自分类Dev

ThreadLocal和泛型

来自分类Dev

如何为泛型类指定泛型集合类型?

来自分类Dev

具有泛型类型的泛型集合生成

来自分类Dev

创建泛型泛型的集合-字典协方差

来自分类Dev

扩展集合泛型类的泛型类

来自分类Dev

具有泛型类型的泛型集合生成

来自分类Dev

可调用和闭包

来自分类Dev

如何调用泛型方法?

来自分类Dev

在泛型上调用方法?

来自分类Dev

泛型的调用对象方法

来自分类Dev

Spring RestTemplate和泛型类型ParameterizedTypeReference集合,例如List <T>

来自分类Dev

Python 3.9和PEP 585中的任何内容-标准集合中的类型提示泛型

来自分类Dev

Java集合、泛型和抽象类:具体类信息丢失

来自分类Dev

C#集合类型约束泛型

来自分类Dev

如何递归遍历嵌套的泛型集合?