What's the difference between Objects.requireNonNullElse() and Optional.ofNullable().orElse()?

There is one minor difference in their behavior. Objects.requireNonNullElse() requires that one of the parameters be non-null, otherwise, a NullPointerException is thrown.

String foo = null, bar = null;
Optional.ofNullable(foo).orElse(bar); //returns a null value
Objects.requireNonNullElse(foo, bar); //throws a NullPointerException

The conceptual difference between choosing one over another is as explained in their documentation. It relies on the approach of an API consumer to choose which one of them is supposed to be used effectively by them.

Optional is container object which may or may not contain a non-null value.

A variable whose type is Optional should never itself be null; it should always point to an Optional instance.

This is a value-based class; use of identity-sensitive operations (including reference equality (==), identity hash code, or synchronization) on instances of Optional may have unpredictable results and should be avoided.

  • ofNullable

    returns an Optional with a present value if the specified value is non-null, otherwise an empty Optional

  • orElse

    returns the value if present otherwise, returns other.

Hence the following behaviour:

String foo = null;
=> Optional.ofNullable(foo).orElse("nonNull")
=> Optional.ofNullable(null).orElse("nonNull")
=> Optional.empty().orElse("nonNull")
=> return otherwise "nonNull"

same as it traverses

String foo = null, bar = null;
=> Optional.ofNullable(foo).orElse(bar);
=> Optional.ofNullable(null).orElse(bar);
=> Optional.empty().orElse(bar)
=> return otherwise 'bar'
=> returns null

Objects is a class consists of static utility methods for operating on objects, or checking certain conditions before an operation.

These utilities include null-safe or null-tolerant methods for computing the hash code of an object, returning a string for an object, comparing two objects, and checking if indexes or sub-range values are out-of-bounds.

  • requireNonNullElse

    returns the first argument if it is non-null and otherwise the second argument if it is non-null

Hence the difference in behaviour:

String foo = null;
=> Objects.requireNonNullElse(foo, "nonNull")
=> Objects.requireNonNullElse(null, "nonNull");

which further evaluates internally if requireNonNull("nonNull", "defaultObj") and then

=> returns "nonNull" since its a non-null value

now as it traverses

String foo = null, bar = null;
=> Objects.requireNonNullElse(foo, bar);
=> Objects.requireNonNullElse(null, bar);

It checks internally if requireNonNull(bar, "defaultObj") which then

=> throws a NullPointerException

As documented as well

throws NullPointerException - if both obj is null and defaultObj is null