为什么Optional.map使此分配有效?

Car*_*den 36 java generics optional java-8

Optional<ArrayList<String>> option = Optional.of(new ArrayList<>());

Optional<ArrayList<?>> doesntWork = option;

Optional<ArrayList<?>> works = option.map(list -> list);
Run Code Online (Sandbox Code Playgroud)

第一次尝试分配不会编译,而第二次则带有mapdo。感觉map应该没有实际完成任何事情,但是由于某种原因,这使我Optional<ArrayList<String>>变成了Optional<ArrayList<?>>。是否存在某种隐式强制转换?

Era*_*ran 25

如果仔细研究的代码map并遵循所有方法调用,您将看到option.map(list -> list)最终返回new Optional<>(option.get())。因此,您可以将上一个作业替换为:

Optional<ArrayList<?>> works = new Optional<>(option.get());
Run Code Online (Sandbox Code Playgroud)

这将创建一个新变量,并使用返回的Optional<ArrayList<?>>初始化其value实例变量(类型为ArrayList<?>)。这是有效的分配。ArrayList<String>map.get()

是否存在某种隐式强制转换?

否,map返回一个新Optional实例。它不会转换调用它的原始实例。

这是方法调用链:

option.map(list -> list)
Run Code Online (Sandbox Code Playgroud)

返回(因为option不为空)

Optional.ofNullable(mapper.apply(value))
Run Code Online (Sandbox Code Playgroud)

在您的情况下与

Optional.ofNullable(value)
Run Code Online (Sandbox Code Playgroud)

返回(因为值不为空):

Optional.of(value)
Run Code Online (Sandbox Code Playgroud)

哪个返回

new Optional<>(value)
Run Code Online (Sandbox Code Playgroud)

  • 另请参阅[此答案](/sf/answers/3836143461/)。它的最后一个代码示例使用map(Function.identity()),其中不可能直接分配Optional。在此问题的上下文中,“ A”将是“ ArrayList &lt;?&gt;”,而“ B”将是“ ArrayList &lt;String&gt;”。 (3认同)

Eug*_*ene 10

好吧,第一个不起作用,因为泛型是不变的,使它们协变的唯一方法是添加一个有界类型,例如:

 Optional<? extends ArrayList<String>> doesntWork = option; 
Run Code Online (Sandbox Code Playgroud)

那会编译。

当您说该map步骤不应完成任何事情时,这是正确的,也不正确。看一下的定义Optional::map

public <U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent()) {
        return empty();
    } else {
        return Optional.ofNullable(mapper.apply(value));
    }
}
Run Code Online (Sandbox Code Playgroud)

粗略地说,它确实从转变Optional<T>Optional<U>...