RFR(s): 8140281 add no-arg Optional.orElseThrow() as preferred alternative to get()

Tagir Valeev amaembo at gmail.com
Mon Dec 18 10:31:47 UTC 2017


Hello!

I think that both methods could co-exist with slightly different
semantics (even though they implementation is identical):

The get() method should be called when it's evident from the narrow
context that Optional is present at the point and using functional
alternatives (like ifPresent()) is inconvenient at this place, e.g.:

  for(X x : list) {
    Y y = calculateYPossiblyThrowingCheckedException(x);
    Optional<T> optional = getOptional(x, y);
    if(optional.isPresent()) {
      return optional.get(); // get() will always succeed
    }
  }
  return null; // or whatever else default value

Such loop is difficult to convert to Stream/Optional chain and not
very easy to get rid of isPresent/get. One possibility is to change to
  T t = getOptional(x, y).orElse(null);
  if(t != null) return t;
But it's really questionable (after all using optionals we want to get
rid of nulls). So I think having get() here is fine. Think of get() as
an assertion-like method: if get() throws, then it's a bug in the code
(most likely right in this method).

The orElseThrow() method should be called when we are not sure that
Optional is present (e.g. it's received from the method call), but we
are fine with default NoSuchElementException. If orElseThrow() throws,
then
it's an acceptable situation (e.g. we are inside the library method
and it documents that NoSuchElementException could be thrown if some
precondition is not met).

In IntelliJ IDEA we warn by default if get() is called and we cannot
statically determine that Optional is always present at this point
(e.g. isPresent() was checked). In future Java we may suggest to
replace with
orElseThrow() in such cases. However I don't like issuing a warning if
get() is used like in the code above. And if get() will be deprecated,
then we would need to issue warning on every get() usage. Thus I'm
against the deprecation.

> I know that you like get() (or at least you're OK with it). But even three
> years after the release of Java 8, I still see bad code written with get(),
> so I don't think this problem is going to go away.

I believe that for any kind of API you can find bad code which abuses
it regardless on how many years passed since the API was released.
That's not always the fault of API creators.

With best regards,
Tagir Valeev.


More information about the core-libs-dev mailing list