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 isnull
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With