我正在尝试使用无界的通配符,因为我有一些可以返回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()来处理在提交的任务中抛出的异常。
那么处理这个问题的正确方法是什么?
答案 0 :(得分:4)
通配符不适用于此处。 (另请注意,如果您有两个通配符,则它们不匹配,就像您具有名为T
和U
的通用参数一样。)
标准方法是使用<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);