{{announcement.body}}
{{announcement.title}}

Consistent Null Values Handling in Java

DZone 's Guide to

Consistent Null Values Handling in Java

Learn more about consistent null values handling in Java.

· Java Zone ·
Free Resource

Learn more about consistent null values handling in Java.

The handling of null values are often considered a weak spot in Java, and there are several reasons for it.

The most frequently mentioned issue is the famous NullPointerException, although there is no clear justification as to why this is an issue. After all, this is just a sign of the problem, but not the problem itself.

The actual problem is deeper. Those who have experience writing code with C or C++ know this issue well. While coding in C/C++, engineers should always keep in mind countless nuances related to access safety, undefined behaviors, memory allocation, object copying/moving, and so forth. All these numerous details create constant "pressure," consume precious engineer brain resources, and result in slower development speed. Even hardcore C/C++ proponents can't deny this fact.

A similar problem exists with null values in Java.

You may also like: 10 Tips to Handle Null Effectively

Java is often considered a verbose language. That's true. This is the backside of its explicitness. Almost every intent in Java can be (and usually is) explicitly expressed in code. By adding some extra text, we, in turn, get immediately accessible context, which doesn't need to be carried in the head while reading Java code. The null values break this rule. They don't manifest themselves in the code.

The null values may appear for various reasons. It can be default initialization, the value returned from some method, or even explicitly assigned null value. Keeping in mind that sometimes null's may appear, checking method documentation or code for the possibility to return such value — all these creates "pressure" very similar to described above for C/C++.

What can be done to solve this issue? How can we remove the constant "pressure" that affects our productivity?

Of course, there is more than one way to solve it.

We can:

  • Add @NotNull (or alike) annotations. Does, basically nothing, except adding some (false) feeling that null values are somehow handled.
  • Establish strict rules and check every value which potentially be null. It's a working solution, but at the expense of polluting code with countless null checks. And, well, nobody is perfect; we can make mistakes and the compiler will not help us.
  • Invent own language. Authors of Kotlin have done just that. Again, this is a working solution, but it's overkill for me. Nevertheless, it has one important thing: nullable and non-nullable types are distinct and clearly expressed in the code.
  • Use functional programming approaches — Maybe monad in some form.

The last point is what I'm going to discuss in more detail.

Optional: The Good, The Bad, and The Ugly

Introduced in Java 8, Optional class is targeted to handle missing values instead of null. To some extent, it is a Java implementation of Maybe monad (but not completely, see below).

While some can consider this as just a fancy way to work with null values, it actually has a far more important benefit: explicit expression of intent. Once you wrap a field, parameter, or variable into Optional, you immediately making your intent explicit and clear to the reader. In other words, you're adding that missing context. At the same time, the compiler starts seeing a difference, so you're not alone anymore.

So, by using Optional, an engineer kills three birds with one stone:

  • Makes potentially missing value explicit in code and removes "pressure" from the reader.
  • Enables compiler to control access to the value.
  • Makes handling of null values convenient.

Unfortunately, Optional has its own issues.

As mentioned above, Optional "to some extent" implementation of Maybe monad. It makes reverences to imperative world and has externally accessible value. By calling the get() method, you can try to retrieve it. But if you do, it may throw NullPointerException, which defies the whole purpose of the Optional — be safe container for potential null (i.e. missing) values.

Perhaps this is why some smart heads suggest that "using Optional for fields and parameters is bad practice" and static analysis tools show warnings for such usage of Optional.

The solution might be to write your own version of Maybe and use it instead. There are several different implementations around. I'm using one from my Reactive Toolbox Core library.

Summary

The Optional/Option/Maybe enables Java engineers to use the following convention:

  • Every variable/field/parameter with plain type is not null and never can be.
  • Every variable/field/parameter whose type is wrapped into Optional/Option/Maybe — potentially can be empty.
  • If some external library/call can return null value, the result should be immediately wrapped into Optional/Option/Maybe.

Without any additional efforts, strict following the convention above enables writing Java code which:

  • Never throws NullPointerException and have all null values handled properly.
  • Clearly and explicitly distinguishes nullable and non-nullable values in code and lets compiler enforce this distinction at compile time.

Further Reading

10 Tips to Handle Null Effectively

Java 8 Optionally: Handling Nulls Effectively

Avoiding NullPointerException in Java 8

Topics:
java

Published at DZone with permission of Sergiy Yevtushenko . See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}