泛型方法调用通配符

时间:2014-07-24 14:42:27

标签: java generics

我有一个方法submit

<T> Future<Optional<T>> submit(Value<T> value) {
    //...
}

并调用此方法。

Value<?> value = null;
Future<Optional<?>> future = submit(value);

但是除非我将签名更改为Future<? extends Optional<?>> future,否则它不会编译,因为submit会返回Future<Optional<caputure of ?>>而不是Future<Optional<?>>,因为泛型是不变的。有没有办法给编译器一个提示并调用方法submit以便返回Future<Optional<?>>

此代码段

<T, E extends Future<Optional<T>>> E submit(Value<T> value) {
  // ...
}
Value<?> value = null;
Future<Optional<?>> future = submit(value);

也会编译但是我需要在返回值之前对E进行不安全的强制转换。

这是一个解释泛型不变性的答案,但它仍然没有回答如何使用捕获的类型。

Multiple wildcards on a generic methods makes Java compiler (and me!) very confused

4 个答案:

答案 0 :(得分:2)

虽然我不确定为什么使用它作为Future<? extends Optional<?>>应该是一个问题,但可能有一个解决方案,取决于你愿意接受多少扭曲和“技巧”。

即使使用additonal类型参数E,也无法以所需的形式进行编译,因为它不是类型安全的。至少,(编译器)不可能确保它是类型安全的。 与最初创建的类型不同的类型。在其他位置,有人可以使用原始类型了解Future<Optional<?>>,并在尝试使用时收到Future。 (我在https://stackoverflow.com/a/22193221/3182664

中用一个更简单的例子解释了这一点

但是...

......这一切与此无关。 Optional接口不允许“设置”任何新值。因此,将其转换为具有其原始类型的超类型的Future是完全可行的。

注意:这类似于您可以写

的事实
ClassCastException

这是有效的(意思是“类型安全”),因为您无法污染Future - 列表中包含无效Future个实例(如List<Integer> integers = new ArrayList<Integer>(); List<Number> numbers = Collections.unmodifiableList(integers); s),因为无法修改无论如何,这个清单!

因此,一种类型安全,无警告且有效的解决方案可能是引入一种“包裹”Integer并将其作为Number返回的方法。再说一遍:这不是很漂亮,可能不值得努力,但至少有一个选择:

Double

答案 1 :(得分:1)

据我所知,没有办法告诉编译器您的代码实际上是正确的。您可以尝试将?替换为Object

Value<Object> value = null;
Future<Optional<Object>> future = submit(value);

答案 2 :(得分:0)

我看不出问题出在哪里。

Future<? extends Optional<?>> future = submit(value);
Optional<?> f = future.get();

编译并正确运行。

您联系的答案非常清楚地解释了这一点:

Foo<Bar>Foo<?>

但是

Foo<Bar<X>>不是Foo<Bar<?>>,而是Foo<? extends Bar<?>>

答案 3 :(得分:0)

您可以更改方法以使用通配符运算符作为参数,因为您未在T上指定任何类型。在我看来,它不会发生太大的变化。

Future<Optional<?>> submit(Value<?> value) {
    //...
}