gpt4 book ai didi

java - 使用通配符调用泛型方法

转载 作者:搜寻专家 更新时间:2023-11-01 03:05:17 25 4
gpt4 key购买 nike

我有一个方法 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

最佳答案

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

即使使用附加类型参数 E 也无法以所需的形式编译它,仅仅是因为它不是类型安全的。至少,(对于编译器)不可能确保它是类型安全的。它可能不是类型安全的原因可以概括如下:有人收到 Future<Optional<?>>可以修改 Future , 并将其分配给任何 Optional - 即使是与最初创建的类型不同的类型。在不同的位置,有人可能知道 Future及其原始类型,并收到ClassCastException尝试使用它时。 (我在 https://stackoverflow.com/a/22193221/3182664 中用一个更简单的例子解释了这一点)

但是……

... 所有这些都与这里无关。 Future接口(interface)不允许“设置”任何新值。因此,将其转换为 Future 是完全可行的。具有其原始类型的父类(super class)型。

注意:这类似于你可以这样写

List<Integer> integers = new ArrayList<Integer>();
List<Number> numbers = Collections.unmodifiableList(integers);

这是有效的(意思是“类型安全”),因为你不能污染 Integer -列表无效 Number实例(如 Double s),因为无论如何都无法修改列表!

因此,一种类型安全、无警告且有效的解决方案可能是引入一种“包装”Future<? extends T> 的方法。并将其作为 Future<T> 返回.再说一次:这不是很漂亮,可能不值得付出努力,但至少有一个选择:

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class GenericOptionalFutureMethod
{
void call()
{
Value<?> value = null;
Future<Optional<?>> future =
FutureWrapper.<Optional<?>>wrap(submit(value));
}

<T> Future<Optional<T>> submit(Value<T> value) {
return null;
}
}

class FutureWrapper
{
static <T> Future<T> wrap(final Future<? extends T> future)
{
return new Future<T>()
{
@Override
public boolean cancel(boolean mayInterruptIfRunning)
{
return future.cancel(mayInterruptIfRunning);
}

@Override
public boolean isCancelled()
{
return future.isCancelled();
}

@Override
public boolean isDone()
{
return future.isDone();
}

@Override
public T get() throws InterruptedException, ExecutionException
{
return future.get();
}

@Override
public T get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException,
TimeoutException
{
return future.get();
}
};
}

}

关于java - 使用通配符调用泛型方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24936842/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com