Reputation: 275
I have read this topic: Avoiding != null statements but I don't see benefits.
If you return empty array, you need to examine where the "real" array is, and where the empty array is.
Instead of using code like getName() != null
, you must use getName().length > 0
. As an example, I'm working on project, where I need to compress some data with few archivers and decided to choose compressed data with the smallest size. If I return null from the archiver "compress" method, I need to check that the returned value is not null. If I decided to return an empty array, then I also need to check it for empty.
Am I right?
Upvotes: 4
Views: 591
Reputation: 137
I had that thought for a while. Leaving the NPE issue aside for a moment. I'll try to explain my thoughts from an OOP point of view.
Let's say you write a class that provides a getter for Glass instance
public Glass getGlass()
.
When I read this signature I'm expecting for some instance of a Glass interface and null isn't one.
You can consider the next approach public Optional<Glass> getGlass()
.
The Optional class (can write your own or use Google's guava Optional) contains your generic class instance while offering the isPresent function among others.
It may seem redundant cause' you could just use getGlass() != null
instead of getGlass().isPresent()
from your client code. But the main advantage here is that the signature is straightforward. No one hides nothing and you don't have to guess.
So you get the benefit of :
Upvotes: 1
Reputation: 43852
The primary advantage of using empty collections or "blank" actions instead of null is that most of the time, such objects will still work in code without further modification. The null
value, at its core, is simply far more prone to errors due to its nature.
Take the following code, for example:
String[] names = data.getNames();
if (names != null) {
for (String name : names) {
// Do stuff
}
}
The check for null
is required or you'll get an NPE. Using a standard for loop does not resolve the problem. On the other hand, if you know you'll always get an array of some kind, your code will work fine with no additional checks. The loop won't run at all if the array is empty. Problem solved.
The same is true for code that implements some form of action. Another example:
Action myAction = data.getActionToRun();
if (myAction != null) {
myAction.run();
}
Once again, you need a null
check. If the action is guaranteed to exist, then you can always call action.run()
with no side effects, yet the blank actions just won't do anything. It's that simple.
In many cases, null
checks can simply be discarded if you modify how methods return, leading to much simpler and understandable code. In some cases, returning null
is the correct choice (for example, getting an object from a collection of keys and values), since there is no default "actionless" value. But null
indicates the lack of a value at all, and it requires additional handling be the receiver. Using blank, actionless, non-null objects allows the error to be handled by the data object. That's good encapsulation. It's good programming. It just works.™
Finally, returning null
is certainly not a good way to handle errors. If something goes wrong in your code that should never go wrong unless you as the programmer made a programming mistake, use assert
s or exceptions. Those are failures. Don't use null
as a failure case, use it as a simple lack of a value.
Upvotes: 11
Reputation: 13097
An empty array is a more natural object to return sometimes. Consider some code like this:
String [] elements = getElements();
for (String element : elements)
System.out.println(element);
If you return an empty array (that is, there are no elements), nothing will be printed and the code will execute correctly. However, if getElements() returns null, you will get a null pointer exception. To prevent it you need to add more code, which makes things more complicated. Returning an empty array allows the desired behaviour to just happen without additional code.
Upvotes: 7