Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.util.Objects vs Optional which is preferable?

The java.util.Objects class was extended with a number of new methods

Objects#requireNonNullElse

respectively

Objects#requireNonNullElseGet() in Java-9.

Both will return the first argument if it is non-null and otherwise returns the non-null second argument or the non-null value of supplier.get()

jshell> String nullStr = null;
nullStr ==> null

jshell> Objects.requireNonNullElse(nullStr,"lorem ipsum");
$13 ==> "lorem ipsum"

jshell> Objects.requireNonNullElseGet(nullStr,() -> "lorem ipsum");
$14 ==> "lorem ipsum"

But the new functionality overlaps with already existing in the Optional class Optional#orElse and Optional#orElseGet

jshell> Optional.ofNullable(nullStr).orElse("lorem ipsum");
$17 ==> "lorem ipsum"

jshell> Optional.ofNullable(nullStr).orElseGet(() -> "lorem ipsum");
$18 ==> "lorem ipsum"

The only difference between new methods in Objects and corresponding Optional methods is that second argument or value of supplier must be non-null otherwise Objects throws NPE:

jshell> Objects.requireNonNullElseGet(nullStr,() -> null);
|  java.lang.NullPointerException thrown: supplier.get()
|        at Objects.requireNonNull (Objects.java:246)
|        at Objects.requireNonNullElseGet (Objects.java:321)
|        at (#15:1)

jshell> Objects.requireNonNullElse(nullStr,null);
|  java.lang.NullPointerException thrown: defaultObj
|        at Objects.requireNonNull (Objects.java:246)
|        at Objects.requireNonNullElse (Objects.java:301)
|        at (#16:1)

versus Optional

jshell> Optional.ofNullable(nullStr).orElse(null);
$19 ==> null

jshell> Optional.ofNullable(nullStr).orElseGet(() -> null);
$20 ==> null
  • Why haven't the JDK developers updated existing methods in Optional class?
  • Why haven't they introduced a new method (which will thrown NPE if second argument is null) to Optional class?
  • What should we use now Optional or Objects?
  • Do new methods make Objects more preferable than Optional since they will throw NPE immediately and not later on somewhere in the code like with Optional?

If I have a legacy code, something like:

String str = null; 
String result = str == null ? "other string" : str;

Which is just a simple check inside a method. And I would like to re-factor it using latest language features. Now having in mind the difference between Optional.orElse and Objects.requireNonNullOrElse which is preferable?

result = Optional.ofNullable(str).orElse("other string");

or

result = Objects.requireNonNullOrElse(str,"other string);
like image 224
Anton Balaniuc Avatar asked Feb 27 '17 09:02

Anton Balaniuc


People also ask

Is it good to use optional in Java?

Optional is a new type introduced in Java 8. It is used to represent a value that may or may not be present. In other words, an Optional object can either contain a non-null value (in which case it is considered present) or it can contain no value at all (in which case it is considered empty).

Is optional better than null?

In a nutshell, the Optional class includes methods to explicitly deal with the cases where a value is present or absent. However, the advantage compared to null references is that the Optional class forces you to think about the case when the value is not present.

Which of the following option is the main advantage of optional in Java?

Java 8 has introduced a new class Optional in java. util package. It is used to represent a value is present or absent. The main advantage of this new construct is that No more too many null checks and NullPointerException .

Which are methods of the optional class and depend on the presence or absence of contained values?

Additional methods that depend on the presence or absence of a contained value are provided, such as orElse() (return a default value if value not present) and ifPresent() (execute a block of code if the value is present).


1 Answers

The shortest answer to your question "which is preferable?" is the all-time developer favorite "it depends" 😜 because Objects::requireNonNullElse and Optional cover different use cases.

The Two Alternatives

Before answering your questions I want to give some background on the two alternatives.

Objects::requireNonNullElse

Objects::requireNonNull makes sure that the result of the call is never null (hence the name). It is usually used to succinctly verify constructor or method arguments and allows readers to verify with a glance that the variable to which the return value is assigned can not be null.

So it would not only be weird for Objects::requireNonNullElse to suddenly allow null, it would also be borderline useless because:

// if requireNonNullGet would allow null as second argument,
// the following is true for all x (including null)
Objects.requireNonNullElse(x, null) == x

You might argue that it is different for requireNonNullElseGet because that might call a function that, depending on some state, might return null or not. That's true and I assume it was considered but the requireNonNull... API would be really weird if one of the three cases might actually allow the final result of the call to be null even though the name says required non null.

Optional

Optional was designed as a return argument in cases where returning null is very likely to cause NPEs (like for a Stream's terminal operation, where it was first used). Although some developers prefer to use it in more cases (compare Stephen Colebourne's pragmatic approach and my strict approach) no one really proposes using it as in your demonstration:

Optional.ofNullable(nullStr).orElse(null);
Optional.ofNullable(nullStr).orElseGet(() -> null);

Optional is a way to express in the type system that something might be missing - it is not meant as an alternative to if-null-checks. In that sense orElse or orElseGet are backdoors out of Optional back into the world of nullable types and sometimes null is just what you want to use if something's not there, so it makes sense for them to accept null as an argument (or the supplier's result).

Your Questions

Now we have what we need to answer your questions:

Why haven't the JDK developers updated existing methods in Optional class?

Conceptually that would go against what Optional should be used for. But, as others have mentioned, this would be a backwards incompatible change as calls to orElse(null) would suddenly throw exceptions.

Why haven't they introduced a new method (which will thrown NPE if second argument is null) to Optional class?

APIs are only extended if considerable improvements of existing code can be expected. I don't see that here. In many cases orElse gets an argument that the caller creates specifically as an alternative for empty optionals - there is rarely a need to make an extra check to verify it's not null. If you really have to, call orElse(requireNonNull(x)).

What should we use now Optional or Objects?

If you have a variable (be it local, an argument or a field) and you want to make sure it's not null, use Objects. If you want to return something, which may be null consider wrapping it in Optional. Be suspicious of code that creates an Optional (as opposed to getting one form a call) and unwraps it at the end of the same chain.

Do new methods make Objects more preferable than Optional since they will throw NPE immediately and not later on somewhere in the code like with Optional?

As I'm sure is clear by now, they cover different use cases. But let me address "and not later on somewhere in the code like with Optional": Whatever you do, make sure to check your desired nullablity property (can be null or not) in your code. Don't return something that you assume can not be null but it turns out to be because you didn't check. If that happens, it's not Optional's fault.

If I have a legacy code, something like:

String str = null; 
String result = str == null ? "other string" : str;

Definitely Objects.requireNonNullOrElse(str,"other string"); and consider using static imports to make it more readable.

like image 132
Nicolai Parlog Avatar answered Sep 29 '22 05:09

Nicolai Parlog