tmn
tmn

Reputation: 11559

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?

Upvotes: 8

Views: 2229

Answers (2)

Holger
Holger

Reputation: 298153

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

Upvotes: 4

Jatin
Jatin

Reputation: 31724

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.

Upvotes: 6

Related Questions