Avoid Null Booleans in Java
Do you prefer boxed primitives?
TL; DR;
These four bullets describe very well the idea of the article:
- Prefer primitive booleans to wrapper Booleans. It is always the best choice as you avoid NPEs, autoboxing complexity, and unnecessary object creation.
- If you are thinking about using a Boolean object because you need a null state, use an Enum instead, it will give you far more information than a null value.
- IMHO Boolean wrappers are just a bad side-effect of the object-oriented approach of Java. They are there, but it doesn’t mean that we should use them ;)
- There are two main special cases where you should use Boolean wrappers:
- To use Generic types (Collections, Maps, Stream, Predicate, etc…). They do not allow primitive values, but you should try to guarantee no null values here.
- To map a third-party API if you have no alternative. Document the meaning of a null value in that field and, whenever possible transform that Boolean into an Enum.
Java boolean variables (the primitive ones) allow only two possible values: true or false, the last one as default.
We use booleans to represent values that only can represent a true or a false statement, such as:
- isEmpty
- hasSomething
- isAlive
- canContinue
- isBlank
- etc
Let’s say that you have a list of tasks to do, and you want to know if the list is empty so you can finally go home. So, is the list empty? If it is (true), then you can go home, if it is not (false), then you have to keep working… does it really make sense for a null answer?
- Subject A: “Hey, is the list empty?”
- Subject B: “I have no idea”
- Subject A: “But should I go home or should I stay here?”
What is the answer? Should subject A keep working? Should he/she wait for a new task?…
Wrapper classes
As Java is an Object Oriented Programming language, it has all its primitive types as classes too.
Integer is the wrapper for the primitive int, Double is the wrapper for the primitive double… you see the point here. Well, Boolean is the wrapper for the primitive boolean. This introduces a third possible status for a boolean variable: As objects are nullable, Booleans are nullable too.
So… a Boolean can be true, false… or null.
What does a null Boolean mean?
A null Boolean means that the variable has no reference assigned, so it is neither true nor false, it is “nothing”.
What can we do with a null boolean?
An example that comes to my mind would be the next one:
Suppose you are working on a weather system, and you consume a third-party API. One of the fields in the JSON response is a Boolean, isTornadoAlert, and it can be true, false, or null.
There are several weather stations, in many countries or cities, that does not report the tornado alert, because they do not have the required infrastructure or because of the typical weather, or whatever… but the thing is that they do not send this isTornadoAlert field, so you won’t get true or false, but you will get null instead.
Well, your weather system provides this information to a website, and then this website shows the tornado alert information:
- If isTornadoAlert is true, then it shows the proper alert.
- If isTornadoAlert is false, then it can proudly say that everything will be ok.
- If isTornadoAlert is null, then it can just omit the information. It has no real information, and say that no tornado will happen would just not be true. It simply doesn’t know.
You can just say that null means false, but that won’t be exactly the truth. At least no in this situation.
Reasons why I believe it is wrong to use null Boolean values
I believe that the possibility of having null values on Boolean variables is a kind of unfortunate side effect, and this is why:
Boolean Algebra
According to Wikipedia*,
Boolean algebra is the branch of algebra in which the values of the variables are the truth values true and false, usually denoted 1 and 0, respectively.
There is not a third possible value for the variables in Boolean algebra. So why should be a null possible value in Boolean variables?
Three-valued logic
It exists the three-valued logic, where a variable can be true, false, or indeterminate. But this kind of logic is not supported by the Java language. There are a few possible truth tables in the three-valued logic, and none of these actually works with null values in Java.
If you try to run this code, you will see what I’m talking about.
Just avoid the Boolean boxed primitive
I strongly recommend not to use the Booleans but to use the primitive type instead. It is always better: No NullPointerException, no autoboxing/unboxing complexity, no object creation, no identity problems.
Instead of using the wrapper class, I prefer the use of enumerated values. Let’s take the isTornadoAlert example.
We could transform the isTornadoAlert Boolean field to an enumerated tornadoAlertStatus with these values:
- TORNADO_INCOMING
- NO_TORNADO_DETECTED
- UNKNOWN_STATUS
The UNKNOWN_STATUS value tells us a little more than the null value and having an enum gives us the possibility to add more values to the response without breaking the whole API.
Exceptional cases
- Generic types:
If you have to use generic types such as Collections, Streams, Maps, Predicates, Functions, Consumer, Suppliers, or your own generic types, you can’t use primitive values. In this situation, you have no alternative but to use the boxed primitive Boolean. However, you should be careful not to have any null value. - Third-Party APIs:
It can happen that some third-party APIs will respond with a Boolean wrapper. If a null value is possible, then I encourage you to document its meaning and, if possible, transform that Boolean to a more representative enum.
Thanks for reading this article!