Java 泛型类型上的流操作链会导致类型错误
以下类和方法:Java 泛型类型上的流操作链会导致类型错误,java,generics,Java,Generics,以下类和方法: class A<T extends B> { } class B {} Stream<A<? extends B>> find() { return findAll() // Stream<Optional<A<? extends B>>> .filter(Optional::isPresent) // Stream<
class A<T extends B> { }
class B {}
Stream<A<? extends B>> find() {
return findAll() // Stream<Optional<A<? extends B>>>
.filter(Optional::isPresent) // Stream<Optional<A<? extends B>>>
.map(Optional::get) // Stream<A<capture of ? extends B>>
.filter(a -> false); // Stream<A<capture of ? extends B>>
}
Stream<Optional<A<? extends B>>> findAll() {
return Stream.empty();
}
(注意,IDEA为
aStream
推断的类型是Stream,这是因为Stream.map
具有以下特征:
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
或者显式地将函数转换为returna您是否尝试过用javac编译它?是的,如上所述--工作正常。您是否检查过您的想法是否与您的javac使用相同的Java版本?类型推断通过Java版本得到了改进,您的编译器可能会更高级一些。我使用Eclipse光子a获得了相同的异常ndjava10。但以下内容对我来说很有用:Stream@LuCio这是我在这个例子中能想到的最简单的谓词;这个例子是基于类似的代码,在最后的过滤器中有一个更复杂的谓词,我认为map
签名清楚地说明了为什么会有协方差问题。所以我猜javac
编译它时没有抱怨的事实是它从我传入的具体函数中推断了返回类型?如果你问为什么你的第二个洞察有效-将表达式一分为二并给中间值一个显式类型有帮助
-那么是的。将它分配给一个variabl具有正确签名的e将具有与上面我的答案中显式强制转换相同的效果。在其中一种情况下,我们显式强制转换,在另一种情况下,它由编译器隐式完成,通过将返回类型赋值给该变量推断返回类型。这不是我的意思-原始的、未更改的代码,没有任何强制转换(隐式或显式)可以用javac(10.0.2)编译。对。在这一点上,我认为没有人会。那么,我会接受这个答案。谢谢@OhleC,非常感谢。很遗憾我们不能一起解决这个问题!
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
<T extends B> Stream<? extends A<? extends B>> find() {
return findAll() // Stream<Optional<A<? extends B>>>
.map(Optional::get) // Stream<A<capture of ? extends B>>
.filter(a -> false); // Stream<A<capture of ? extends B>>
}
<T extends B> Stream<A<? extends B>> find() {
return findAll()
.map((Function<Optional<A<? extends B>>, A<? extends B>>) Optional::get)
.filter(a -> false);
}