I know that the best practice for handling null
primitives was to use a boxed wrapper, such as Integer
instead of int
, as discussed here
Null for primitive data types
However, does this still remain true today with Java 8 which
introduced optional primitives such as OptionalInt
, whose OptionalInt.empty()
effectively represents a null
value? My understanding is that Optionals should only be used for method return types, not as types for the properties themselves. Should "nullable" primitives still be stored as boxed properties? Should they only be Optional
in the method return types? Or be stored as OptionalInt
in the property itself?
Java primitive types (such as int , double , or float ) cannot have null values, which you must consider in choosing your result expression and host expression types.
Primitive values cannot be null . A variable of a primitive type always holds a primitive value of that exact primitive type. For type double , the default value is positive zero, that is, 0.0d .
Primitive data types - includes byte , short , int , long , float , double , boolean and char.
A function that is associated with an object via a property is called a method. So, yes, null is a primitive value. Show activity on this post. As you can see null, Arrays, and Objects are all Objects.
Suppose you have a method
public void logRequest(Integer userID, String content){
//log content locally or in db or a rest call
}
Suppose you obtain the userID
from database for a particular user. There can be following possibilities:
So now if no id was found, what do you pass to logRequest
?
null
? What if the method didnt have appropriate null check. What should it infer null
to? 0
or -1
? If null
means 0
then it might contradict with an actual user whose ID is 0
. How do you distinguish null and 0?Of-course the above problem can be solved by proper documentation and fixing the rules, but it gives rise to higher maintenance and is error prone. And properly written code should be its own documentation.
Now say the method was declared as:
public void logRequest(OptionalInt userID, String content)
The method itself makes it very clear that it expects an argument which is optional. So there are only 2 case to handle: An appropriate argument is sent (which means no-bypassing by using 0
). If the optional was empty, then method rightly knows how to handle. (Unlike before where we had to read its documentation to predict the behavior).
So the method declaration it self makes it clear on the behavior rather than documentation doing it for you and relying on documentation and wild-guessing. Optionals are quite useful in such scenarios.
PS: I always feel a pinch passing null
to a method expecting an Integer
. It definitely feels wrong! Gosh, in Java the sub-conscious mind always treats ints as primitives. They are not meant to be nulled.
In the answers to the question you have linked, is an explanation about why primitive values can’t be null
. There is not the slightest suggestion that using boxed values for representing null
is “best practice”, in fact, it has not been said that using null
is a good practice at all.
Instead of trying to emulate null
values for primitive types you should take a step back and think about what you are going to express. That semantics might b expressed using a variety of options, using null
not necessarily being one of the best choices. One simple way of expressing uninitialized or “cleared” values is to have an additional boolean fooPropertyInitialized
variable. It’s much clearer than using null
and its overhead is not necessarily bigger than boxing of primitive values.
That would also apply to the API. Don’t use Optional
for a property. Just provide a clearFooProperty()
method, if you want to support such an operation, plus an isFooPropertyInitialized()
. It’s much cleaner to have getFooProperty()
throwing an exception if the caller failed to check the initialized
state first.
Note that’s also possible to simply use a value outside the range valid for a certain context to express special conditions. That’s common practice like InputStream.read()
methods returning -1
to signal reaching the end.
Optional
is the ideal return type for an operation whereas there is no storage for the result so you can’t split querying for the presence and the value into two method invocations and the value range of of present values is not limited.
But as said, without knowing what kind of semantics you want to express, we can’t make a recommendation and there might be more than one possible solution without a “best practice”…
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With