问题
The below code prints:
should Not have called
hello world
Why is orElse
getting executed even when we have an Optional that contains a value?
public static void main(String[] args){
String o = Optional.ofNullable("world").map(str -> "hello" + str).orElse(dontCallMe());
System.out.println(o);
}
private static String dontCallMe() {
System.out.println("should Not have called");
return "why god why";
}
回答1:
The orElse
method looks like this:
public T orElse(T other) {
return value != null ? value : other;
}
There isn't any complex logic here.
As with any method, it will do the following:
- Get the actual values of all parameters passed to the method (which includes calling any methods in those parameters).
- Pass those parameters to the method.
- Execute the method.
The fact that we don't actually care about the value of the parameter doesn't change this process (this is just the way the language has been designed, for better or worse).
If you're looking to not call the method in the parameter, you're probably looking for Optional.orElseGet.
This:
public static void main(String[] args){
String o = Optional.ofNullable("world").map(str -> "hello" + str)
.orElseGet(() -> dontCallMe());
System.out.println(o);
}
private static String dontCallMe() {
System.out.println("should not have called");
return "why oh why";
}
Outputs only:
helloworld
The difference here is that the thing (Supplier) we're passing to the method will stay () -> dontCallMe()
, it does not become () -> "why oh why"
- only when you call get
does it actually evaluate what's going on there and does dontCallMe
actually get called.
回答2:
Please, can somebody explain why
orElse
is getting executed event after map will get executed for final result.
With the orElse method regardless if the wrapped value is present or not, the default object is created.
Hence when you call the function dontCallMe()
in the orElse to return the string value; "should Not have called" will be printed to the console.
Using orElseGet instead of orElse would provide the result you expected although you should only use this method either when the default value is computationally expensive to create or you want to be sure this is done if and only if the value is absent (empty optional) in which case it's a necessity.
As an aside, there's no need to use Optional.ofNullable
here, the Optional.of
method is more appropriate as the former should only be used if the argument can be null and the latter only if the argument cannot be null.
As a reading, you can check out this good post on the baeldung site.
Guide To Java 8 Optional
来源:https://stackoverflow.com/questions/49587576/parameter-of-optional-orelse-gets-called-even-when-optional-contains-value