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

时间:2019-04-04 08:12:36

标签: java generics java-8 optional

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

Optional<ArrayList<?>> doesntWork = option;

Optional<ArrayList<?>> works = option.map(list -> list);

第一个尝试的赋值不会编译,但是第二个带有map的赋值会编译。感觉map实际上不应该做任何事情,但是由于某种原因,它使我的Optional<ArrayList<String>>变成了Optional<ArrayList<?>>。是否存在某种隐式强制转换?

4 个答案:

答案 0 :(得分:25)

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

Optional<ArrayList<?>> works = new Optional<>(option.get());

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

  

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

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

这是方法调用的链:

option.map(list -> list)

返回(因为option不为空)

Optional.ofNullable(mapper.apply(value))

与您的情况相同

Optional.ofNullable(value)

返回(因为值不为空):

Optional.of(value)

返回

new Optional<>(value)

答案 1 :(得分:10)

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

 Optional<? extends ArrayList<String>> doesntWork = option; 

可以编译。

并且当您说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));
    }
}

粗略地说,它是从Optional<T>转换为Optional<U> ...

答案 2 :(得分:0)

您的option.map具有签名

<ArrayList<?>> Optional<ArrayList<?>> java.util.Optional.map(Function<? super ArrayList<String>, ? extends ArrayList<?>> mapper)

所以这个

Optional<? extends ArrayList<?>> doesntWork = option;

可以编译。

答案 3 :(得分:0)

在后一种情况下,Optional.map方法的返回类型由works变量的类型隐式确定。这就是为什么存在差异的原因。