RFR 9: 8138963 : java.lang.Objects new method to default to non-null

John Rose john.r.rose at oracle.com
Fri Oct 9 00:31:58 UTC 2015


On Oct 8, 2015, at 2:42 PM, Roger Riggs <Roger.Riggs at Oracle.com> wrote:
> 
> Thanks for the insight, I hope it will help cut down on the thrashing.
> 
> Isn't there a 4th form that throws missing?

There are four forms in Optional, but one of them returns "void" and is not relevant here, IMO.  The third one I pointed out is the one that throws a programmable exception (e.g., IAE instead of NPE).

> There was quite a bit of support for a version the never returned null and threw an exception if the replacement was null.

This particular concern also transfers from Optional, with some forcing:  Just as Optional::orElse cannot turn around and return an Optional::empty value, nonNullElse should not turn around and return a null.  But, of course, the reason Optional::orElse doesn't return an empty is that the Java types forbid it (T != Optional<T>) while the issue is allowed by Java's always-nullable ref types.

Anyway, I agree with the consensus that nonNullElse and nonNullElseGet should throw NPE instead of returning nulls.

It may be instructive to link nulls to Optionals by encoding null-ness using Optional:

<T> T nonNullElse(T x, T y) := Optional.ofNullable(x).orElseGet(() -> Optional.ofNullable(y).get())

<T> T nonNullElseGet(T x, Supplier<T> y) := Optional.ofNullable(x).orElseGet(() -> Optional.ofNullable(y.get()).get())

or:

<T> T nonNullElse(T x, T y) := Objects.requireNonNull( Optional.ofNullable(x).orElse(y) )

<T> T nonNullElseGet(T x, Supplier<T> y) := Objects.requireNonNull( Optional.ofNullable(x).orElseGet(y) )

This leads me to yet another bikeshed color, FWIW:

 - T requireNonNull(T) (cf. Optional::get)
 - T requireNonNullElse(T,T) (cf. Optional::orElse)
 - T requireNonNullElseGet(T,Supplier<T>) (cf. Optional::orElseGet)
 - T requireNonNullElseThrow(T,Supplier<X>) (cf. Optional::orElseThrow)
 - T requireNonNull(T,String) (shorthand for common use of requireNonNullElseThrow)

This spelling makes it abundantly clear that the return value will *never* be null, unlike some other APIs.

I can imagine being content, as an IDE user, to see all of those options together, from a single completion gesture.

— John


More information about the core-libs-dev mailing list