1

我正在尝试使用无界通配符,因为我有一些返回对象的 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

4 回答 4

4

通配符在这里不合适。(另请注意,如果您有两个通配符,它​​们不匹配,就像您有名为Tand的通用参数一样U。)

标准方法是使用<Void>.

于 2013-08-28T09:21:01.327 回答
0

尝试这个

    CompletionService<Object> ecs = ...;
    Callable<Object> c = ...;
    Future<?> f = ecs.submit(c);
于 2013-08-28T09:25:27.267 回答
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);
}

你可能会在 line 中得到警告CompletionService<T> ecs = ...,但你可以抑制它(仅在此处)。其余的代码应该没问题。

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

于 2013-08-28T09:26:43.397 回答
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);
于 2013-08-28T09:29:22.423 回答