How can one avoid explicitly throwing an Exception
while trying to get the value from an Optional
or while making use of Optional.get
?
Currently, this is possibly safeguarded with the API orElseThrow
as :
// exception could be replaced with any other
Integer opt = anyOddInStream.orElseThrow(
() -> new NoSuchElementException("No value present"));
and yet the directly implementing the get
disappoints(when one might not be willing to explicitly throw an exception) while trying to access something like
// the following not only just fails but throws an exception as well
Integer previous = anyOddInStream.get();
What if one wants to make sure that the Optional
either has a value and if it doesn't they wouldn't want to continue propagating null
ahead?
Java 8 was a huge improvement to the platform, but one of the few mistakes we made was the naming of Optional.get()
, because the name just invites people to call it without calling isPresent()
, undermining the whole point of using Optional
in the first place. (If this was the worst mistake we made in such a big release, then we did pretty well.)
During the Java 9 time frame, we proposed to deprecate Optional.get()
, but the public response to that was ... let's say cold. As a smaller step, we introduced orElseThrow()
in 10 (see https://bugs.openjdk.java.net/browse/JDK-8140281) as a more transparently named synonym for the current pernicious behavior of get()
. IDEs warn on unconditional use of get()
, but not on orElseThrow()
, which is a step forward in teaching people to code better. The question is, in a sense, a "glass half empty" view of the current situation; get()
is still problematic.
We'd love to improve the situation further in future version, but it will probably take some time to bring more of the community around.
From my point of view, Optional.get()
is the code smell. Very often combined with Optional.isPresent()
, it completely defeats the purpose and the idea of Optional.get()
. Here's a more complete reasoning and discussion:
http://royvanrijn.com/blog/2016/04/deprecating-optional-get/
So simply don't use Optional.get()
. If you want to return null
for the absent value, call Optional.orElse(null)
.
An alternate method to get value of an optional instead of Optional.get
(which more likely than not fails to keep up with user's expectations) is to replace it with a more verbose API introduced in JDK10 termed as Optional.orElseThrow()
. In author's words -
Optional.get()
is an "attractive nuisance" and is too tempting for
programmers, leading to frequent errors. People don't expect a getter
to throw an exception. A replacement API for Optional.get()
with
equivalent semantics should be added.
Optional<Integer> anyOddInStream = Stream.of(2, 4, 6, 8)
.filter(x -> x % 2 == 1)
.findAny();
// one could be well aware of the possible exception handling while reading this
var current = anyOddInStream.orElseThrow();
Note :- The underlying implementation of both these APIs is same, yet the latter reads out more clearly that a NoSuchElementException
would be thrown by default if the value is not present which inlines to the existing Optional.orElseThrow(Supplier<? extends X> exceptionSupplier)
implementation used by consumers as an explicit alternative.