简体   繁体   中英

java 8 Optional map() throw NPE with function reference but not with full lambda syntax

Is this a bug or a feature?

Below fails with NPE

Function<String, String> f = null;
Optional.<String>empty().map(f).orElse(null);

But not

Function<String, String> f = null;
Optional.<String>empty().map(value -> f.apply(value)).orElse(null);

IntelliJ for example would suggest to replace the second expression by the first one as equivalent, which made sense to me, until now.

The reason for this behavior is the implementation of Optional#map() :

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    // check happens before the branching
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}

Instead, if map() was implemented with:

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    if (!isPresent())
        return empty();
    else {
        // the check happens only when relevant
        Objects.requireNonNull(mapper);
        return Optional.ofNullable(mapper.apply(value));
    }
}

we would get a consistent behavior between the first 2 snippets. Any reason why map() is not the second implementation?

This is not a bug because it is explicitely documented. Quoting Optional.map(mapper) Javadoc:

If a value is present, apply the provided mapping function to it [...]
...

Throws:

NullPointerException - if the mapping function is null

So the map method always throw a NullPointerException , regardless of the presence of a value or not, if the mapper given is null : this explains the exception in the first case. However, the mapper is only applied if there is a value: this explains why there is no exception in the second case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM