正确使用无界通配符泛型

时间:2013-08-28 09:14:07

标签: java multithreading generics

我正在尝试使用无界的通配符,因为我有一些可以返回Object的Callable,但我对该对象不感兴趣(它们返回null,我只是使用Callable而不是Runnable来抛出已检查的异常)。

所以原则上我想这样做:

CompletionService<?> ecs = ...
Callable<?> = ...
Future<?> f = ecs.submit(c);

但在这里我得到一个错误说:

  

类型中的方法submit(Callable<capture#1-of ?>)   CompletionService<capture#1-of ?>不适用于参数   (Callable<capture#2-of ?>

稍后我只想调用f.get()来处理在提交的任务中抛出的异常。

那么处理这个问题的正确方法是什么?

4 个答案:

答案 0 :(得分:4)

通配符不适用于此处。 (另请注意,如果您有两个通配符,则它们不匹配,就像您具有名为TU的通用参数一样。)

标准方法是使用<Void>

答案 1 :(得分:0)

试试这个

    CompletionService<Object> ecs = ...;
    Callable<Object> c = ...;
    Future<?> f = ecs.submit(c);

答案 2 :(得分:0)

这里的问题是?不是标识符。这意味着“未知的东西”。第一个“未知的东西”与第二个不同。换句话说,您认为要将Callable<C>提交给CompletionService<S>。显然它无法奏效。

解决此问题的方法是使用Object作为泛型类型:

CompletionService<?> ecs = ...
Callable<?> = ...
Future<?> f = ecs.submit(c);

或者,更好的是,在方法级别定义自己的类型T并在代码中使用它:

<T> void foo() {
    CompletionService<T> ecs = ...
    Callable<T> = ...
    Future<?> f = ecs.submit(c);
}

您可能会在第CompletionService<T> ecs = ...行进行警告,但您可以禁止它(仅限此处)。其余的代码应该没问题。

然而,这个建议听起来不是一个好习惯。已经在Java编程语言中添加了泛型,以解决未知类型的问题。因此,更好的方法是在整个代码中正确使用泛型。

答案 3 :(得分:0)

您需要一个类型变量才能声明所有对象的类型参数匹配,即使您对类型本身不感兴趣。为了声明一个类型变量,你必须将代码放在一个可以声明它的方法或构造函数中,例如。

static <T> Future<T> doIt(Callable<T> c, Executor e) {
  CompletionService<T> ecs = new ExecutorCompletionService<T>(e);
  return ecs.submit(c);
}

现在你甚至可以用通配符调用它:

Callable<?> c;
Executor e;
Future<?> f=doIt(c, e);