在oracle docs中,它似乎是
<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)
对于mapper
作为Function
,它会使参数反变,但不会使返回类型变为协变。我想知道mapper
是否可以(应该)
Function<? super T,Optional<? extends U>>
或
Function<? super T, ? extends Optional<? extends U>>
答案 0 :(得分:1)
首先,IMO,因为U
绑定到方法本身而不是类Optional
以及Optional
是final
,所以当前签名应该可以正常工作。
如果上述两个条件不成立,则可以应用更改。感谢@MalteHartwig提供的link。让我总结一下这个特定问题的答案。很明显,如果返回类型需要协变,后一个签名(较长的签名)在Java 8中是必需的。它不仅仅是关于继承。 ? extends
前需要Optional<? extends U>
,即使Function
为Optional
,也要声明final
的用户网站差异。我制作了一个代码片段来演示它:
import java.util.function.Function;
class A {}
class B extends A {}
final public class Option<T> {
private T value;
public Option(T v) { value = v; }
<U> Option<? extends U> flatMap1(Function<? super T, Option<? extends U>> mapper) {
return mapper.apply(value);
}
<U> Option<? extends U> flatMap2(Function<? super T, ? extends Option<? extends U>> mapper) {
return mapper.apply(value);
}
void test() {
Option<A> oa = new Option<>(new A());
Function<A,Option<A>> faa = (A a) -> new Option<>(new A());
Function<A,Option<B>> fab = (A a) -> new Option<>(new B());
//oa.flatMap1(faa); DOES NOT COMPILE
oa.flatMap2(fab);
}
}
似乎由于Java只有用户站点方差声明,你可能需要一系列? extends
将声明一直传播到你要声明方差的类型变量的(第二个)最外层。对
答案 1 :(得分:0)
假设您有class A
和class B extends A
;你需要记住一个对象B
是一个A
对象;你继承了它。
为了使Object满足Optional<? extends U>
约束,它必须满足Optional<U>
约束。同样,为了使对象满足Optional<U>
约束,它必须已满足Optional<? extends U>
。
在这种情况下,它们是同义词。
虽然问题是针对某种方法的,但您可以相当容易地测试答案。通过编写类似的函数,您可以测试编译器是否允许您想要的内容以及它是否会按预期运行。
public static <U> void List(List<U> A, List<? extends U> B) {
...
}
...
MakeList(new ArrayList<Number>(), new ArrayList<Integer>());
正如所料,一切都很好。