4

I have read this topic: Avoiding != null statements but I don't see benefits.

  1. If you return empty array, you need to examine where the "real" array is, and where the empty array is.

  2. 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?

Community
  • 1
  • 1
Avershin Dmitry
  • 265
  • 2
  • 10
  • I'm against totally avoiding something, unless it is shown to be totally bad to use. In this case, if empty array/list and null convey different meanings, then null should be used. If null and empty array/list does not convey special meaning by themselves, then they can be used interchangeably to make the code cleaner. – nhahtdh Jul 20 '12 at 05:10
  • I don't understand your first point. What is the "real" array? If you're returning `null`, that *should* be the real array. If it's an error case, throw an exception. – Alexis King Jul 20 '12 at 05:18
  • @JakeKing,do you read my example?I have compress function,if that function return empty array,than decompress function will fail,because of its implementation,which requires to check first byte of it,so I need to check this situation. – Avershin Dmitry Jul 20 '12 at 05:23
  • +1 to the question for not just reading about a pattern on the internets and accepting it as gospel without asking why. People can get pretty dogmatic about things like `null`. – yshavit Jul 20 '12 at 05:40
  • 2
    @AvershinDmitry Yes, but the fundamental solution here is not to return `null` in that case. If you receive `null` from your compress function, something's wrong. Throw an exception if there's an error instead. – Alexis King Jul 20 '12 at 05:58

3 Answers3

11

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 asserts or exceptions. Those are failures. Don't use null as a failure case, use it as a simple lack of a value.

Alexis King
  • 43,109
  • 15
  • 131
  • 205
  • Very helpful,thanks.This means that in my example it's better to return empty array when compress function can't compress and before adding data to list check this data to be not empty to avoid NPE – Avershin Dmitry Jul 20 '12 at 05:31
  • 2
    @AvershinDmitry That's not necessarily the best solution. It sounds to me like the method should *never* return a null value (or an empty array), unless there's an error. That's not a good idea. If there's an error, throw an exception instead. – Alexis King Jul 20 '12 at 06:00
7

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.

Oleksi
  • 12,947
  • 4
  • 56
  • 80
1

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 :

  1. avoiding NPE's
  2. straightforward signature
  3. clean client code
Alexis King
  • 43,109
  • 15
  • 131
  • 205
R-E-L
  • 137
  • 3