Java 使用通配符的泛型方法调用
我有一个方法Java 使用通配符的泛型方法调用,java,generics,Java,Generics,我有一个方法submit: <T> Future<Optional<T>> submit(Value<T> value) { //... } 也可以编译,但在返回值之前,我需要对E执行不安全的强制转换 这里有一个解释泛型不变性的答案,但它仍然没有回答如何使用捕获的类型 据我所知,没有办法告诉编译器您的代码实际上是正确的。您可以尝试用对象替换?: Value<Object> value = null; Future<Opt
submit
:
<T> Future<Optional<T>> submit(Value<T> value) {
//...
}
也可以编译,但在返回值之前,我需要对E执行不安全的强制转换
这里有一个解释泛型不变性的答案,但它仍然没有回答如何使用捕获的类型
据我所知,没有办法告诉编译器您的代码实际上是正确的。您可以尝试用
对象替换?
:
Value<Object> value = null;
Future<Optional<Object>> future = submit(value);
Value=null;
未来=提交(值);
我看不出问题真正出在哪里
Future<? extends Optional<?>> future = submit(value);
Optional<?> f = future.get();
Future>Future=submit(值);
可选f=future.get();
正确编译和运行
您链接的答案非常清楚地解释了这一点:
Foo
是一个Foo
但是
Foo
不是Foo您可以更改方法以使用通配符运算符作为参数,因为您没有在t
上指定任何类型。在我看来,这不会有多大变化
Future<Optional<?>> submit(Value<?> value) {
//...
}
Future虽然我不确定为什么将其用作Future>
应该是个问题,但根据您愿意接受的扭曲和“技巧”的数量,可能会有一个解决方案
即使使用附加类型参数E
,也不可能以所需的形式编译它,因为它不是类型安全的。至少,(对于编译器)不可能确保它是类型安全的。它不能是类型安全的原因可以总结如下:有人收到未来为什么这是一个问题?就我所知,这没有实际的区别,future.get()
将返回一个可选的对象。不幸的是值
作为参数传递给我,我无法更改它的签名您可以将其转换为值
。我认为ClassCastException的风险很低,因为不管实际的泛型是什么,它总是对象@mvieghofer的派生,你可以,但你不必。将Foo
转换为Foo
几乎肯定是设计错误的标志。@biziclop我同意你的观点,但我也认为将值
传递给任何方法(这里似乎是这样)也是一种糟糕的设计。最好的方法是去掉值
参数。@mvieghofer那么呢?传递无界通配符参数通常是设计不好的标志,但它有其合法用途。当然,它会有很大的变化,因为在?
版本中,输入参数的类型不必与返回值匹配。因此,您可以将Value
传递给该方法,但返回Future
,这可能不是该方法应该做的。submit方法应该是类型化的,这意味着返回类型和参数类型应该匹配是的,我知道,但他在他的示例中没有这样做,这意味着他不关心具体的回报类型。这就是为什么我写到在这种情况下变化不大。如果你说你需要匹配参数,那么为什么你没有用一个特定的参数传递value
,而不是通配符运算符?问题是可选实际上是可选的,我希望有一种方法可以告诉编译器不要在方法签名或方法调用中,以便未来的签名可以保留可选性这就是告诉它的方法。列表
示例向您展示了原因。为什么带有E
的代码段可以工作?在这种情况下,它看起来像?不是captured@user2961393因为E
必须绑定到特定的类,该类在整个表达式中具有相同的值。而?
字面意思是任何东西都可以进入那里。我仍然不明白你为什么要进行不安全的强制转换来避免正确的符号。你的例子只是更改了future的签名,使其与future匹配?如果仍然捕获,则应该有一个更干净的解决方案,它不需要“松散”未来的类型,即未来的代码
Future<? extends Optional<?>> future = submit(value);
Optional<?> f = future.get();
Future<Optional<?>> submit(Value<?> value) {
//...
}
List<Integer> integers = new ArrayList<Integer>();
List<Number> numbers = Collections.unmodifiableList(integers);
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();
}
};
}
}