Having been using Java 8 now for 6+ months or so, I\'m pretty happy with the new API changes. One area I\'m still not confident in is when to use Optional
. I se
Here are some of the methods that you can perform on an instance of Optional
:
map
flatMap
orElse
orElseThrow
ifPresentOrElse
get
Here are all the methods that you can perform on null
:
This is really an apples to oranges comparison: Optional
is an actual instance of an object (unless it is null
… but that would probably be a bug) while null
is an aborted object. All you can do with null
is check whether it is in fact null
, or not. So if you like to use methods on objects, Optional
is for you; if you like to branch on special literals, null
is for you.
null
does not compose. You simply can’t compose a value which you can only branch on. But Optional
does compose.
You can, for instance, make arbitrary long chains of “apply this function if non-empty” by using map
. Or you can effectively make an imperative block of code which consumes the optional if it is non-empty by using ifPresent
. Or you can make an “if/else” by using ifPresentOrElse
, which consumes the non-empty optional if it is non-empty or else executes some other code.
…And it is at this point that we run into the true limitations of the language in my opinion: for very imperative code you have to wrap them in lambdas and pass them to methods:
opt.ifPresentOrElse(
string -> { // if present...
// ...
}, () -> { // or else...
// ...
}
);
That might not be good enough for some people, style-wise.
It would be more seamless if Optional
was an algebraic data type that we could pattern match on (this is obviously pseudo-code:
match (opt) {
Present(str) => {
// ...
}
Empty =>{
// ...
}
}
But anyway, in summary: Optional
is a pretty robust empty-or-present object. null
is just a sentinel value.
There seems to be a few people who effectively argue that efficiency should determine whether one should use Optional
or branch on the null
sentinel value. That seems a bit like making hard and fast rules on when to make objects rather than primitives in the general case. I think it’s a bit ridiculous to use that as the starting point for this discussion when you’re already working in a language where it’s idiomatic to make objects left-and-right, top to bottom, all the time (in my opinion).