Consistent Null Values Handling in Java
Learn more about consistent null values handling in Java.
Join the DZone community and get the full member experience.
Join For FreeThe 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 thatnull
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 countlessnull
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 intoOptional
/Option
/Maybe
.
Without any additional efforts, strict following the convention above enables writing Java code which:
- Never throws
NullPointerException
and have allnull
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
Published at DZone with permission of Sergiy Yevtushenko. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments