可选Java 8中flatMap的签名

huo*_*ter 13 java optional java-8

oracle文档中,它似乎是

<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)
Run Code Online (Sandbox Code Playgroud)

对于mappera Function,它使参数反变,但不使返回类型协变.我想知道是否mapper可以(应该)

Function<? super T,Optional<? extends U>>
Run Code Online (Sandbox Code Playgroud)

要么

Function<? super T, ? extends Optional<? extends U>>
Run Code Online (Sandbox Code Playgroud)

huo*_*ter 1

首先,IMO,因为U绑定到方法本身而不是类Optional,并且也是Optionalfinal所以当前的签名应该可以正常工作。

如果上述两个条件不成立,则可以应用更改。感谢@MalteHartwig 提供的链接。让我总结一下这个特定问题的答案。很明显,如果返回类型需要协变,则在 Java 8 中后一个签名(较长的签名)是必要的。这不仅仅是关于继承。? extends需要在前面声明即使是时的Optional<? extends U>用户站点方差。我制作了一个代码片段来演示它:FunctionOptionalfinal

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

看来,由于 Java 只有用户站点差异声明,因此您可能需要一系列? extends将该声明从要为其声明差异的类型变量一直传播到(第二)最外层。