Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Primitive "nulls" and Java 8

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?

like image 427
tmn Avatar asked Apr 10 '15 03:04

tmn


People also ask

Can primitives be null in Java?

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.

How do you know if a primitive is null?

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 .

What are 8 Java primitive types?

Primitive data types - includes byte , short , int , long , float , double , boolean and char.

Why null is primitive?

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.


2 Answers

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:

  • DB returns a userID.
  • No id found.

So now if no id was found, what do you pass to logRequest?

  • Do you pass null? What if the method didnt have appropriate null check. What should it infer null to?
  • Should you pass 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.

like image 142
Jatin Avatar answered Sep 19 '22 08:09

Jatin


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”…

like image 38
Holger Avatar answered Sep 21 '22 08:09

Holger