Why does Optional.map make this assignment work?

亡梦爱人 提交于 2021-02-15 12:06:16

问题


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

Optional<ArrayList<?>> doesntWork = option;

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

The first attempted assignment does not compile, but the second one with the map does. It feels like the map shouldn't actually accomplish anything, but for some reason it turns my Optional<ArrayList<String>> into an Optional<ArrayList<?>>. Is there some sort of implicit cast going on?


回答1:


If you look into the code of map and follow all the method calls, you'll see that option.map(list -> list) ends up returning new Optional<>(option.get()). So you can replace your last assignment with:

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

This creates a new Optional<ArrayList<?>> and initializes its value instance variable (whose type is ArrayList<?>) with the ArrayList<String> returned by map.get(). This is a valid assignment.

Is there some sort of implicit cast going on?

No, map returns a new Optional instance. It doesn't cast the original instance on which it was called.

Here's the chain of method calls:

option.map(list -> list)

returns (since option is not empty)

Optional.ofNullable(mapper.apply(value))

which in your case is the same as

Optional.ofNullable(value)

which returns (since the value is not null):

Optional.of(value)

which returns

new Optional<>(value)



回答2:


Well the first one does not work because generics are invariant, the only way to make them covariant is to add a bounded type for example:

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

that would compile.

And when you say that the map step should no accomplish anything is well, not correct. Look at the definition of 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));
    }
}

roughly speaking it does transform from Optional<T> to Optional<U>...




回答3:


Your option.map has the signature

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

So this

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

does compile.




回答4:


In your latter case the return type of the Optional.map method is implicitly determined by the type of your works variable. That's why there is a difference.



来源:https://stackoverflow.com/questions/55510951/why-does-optional-map-make-this-assignment-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!