Java 8 的可选版本中 flatMap 的签名

2022-09-04 23:31:16

预言机文档中,它似乎是

<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper)

对于 as ,它使参数逆变,但不使返回类型协变。我想知道是否可以(应该)是mapperFunctionmapper

Function<? super T,Optional<? extends U>>

Function<? super T, ? extends Optional<? extends U>>

?


答案 1

首先,IMO,由于绑定到方法本身而不是类,并且也是,因此当前签名应该可以正常工作。UOptionalOptionalfinal

如果上述两个条件之一不成立,则可以应用更改。感谢您@MalteHartwig提供的链接。让我总结一下这个具体问题的答案。很明显,如果返回类型需要协变,则在 Java 8 中需要后一个签名(较长的签名)。这不仅仅是关于继承。 需要在 前面声明用户站点方差,即使 is 是 。我做了一个代码片段来演示它:? extendsOptional<? 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);
  }
}

似乎由于 Java 只有用户站点方差声明,因此您可能需要一系列声明,这些声明从要声明方差的类型变量一直传播到(第 2 个)最外层。? extends


答案 2

假设你有和 ;你需要记住,一个对象是一个对象;你从它继承。class Aclass B extends ABA

为了使对象满足约束,它必须满足约束。同样,为了使对象满足约束,它必须满足 。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>());

正如预期的那样,一切都很好。


推荐