我有一个方法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
答案 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) {
//...
}