Levels of Helpfulness in Helpful Null Pointers

Java introduced Helpful Null Pointers. Let’s take a look at a few versions using this class:

public class Helpful {
  private String name;
  private Helpful(String name) {
    this.name = name.toUpperCase();
  }
  public static void main(String... args) {
     new Helpful(null);
  }
}

Three approaches

First lets’ run this using Java 11. We get the stack trace

Exception in thread “main” java.lang.NullPointerException
at Helpful.(Helpful.java:4)
at Helpful.main(Helpful.java:7)

Well that’s not helpful. I have to go look at line 4 to even have a clue what is going on. Now let’s run it in Java 17. (Because I’m sticking with Long Term Support versions)

Exception in thread “main” java.lang.NullPointerException: Cannot invoke “String.toUpperCase()” because “<parameter 1>” is null
at Helpful.(Helpful.java:4)
at Helpful.main(Helpful.java:7)

That’s more helpful. It tell us the toUppercase() call is the problem. And that a constructor was the cause. It would be even more helpful to know the name of the variable. This requires a command line flag. Compile with -g:vars and you get this when running

Exception in thread “main” java.lang.NullPointerException: Cannot invoke “String.toUpperCase()” because “name” is null
at Helpful.(Unknown Source)
at Helpful.main(Unknown Source)

Conveniently, both Eclipse and IntelliJ turn on this flag by default.

Never return Null Arrays!

Continuing on Jeanne’s theme of nulls, its a pet peeve of mine when I come across code that returns null arrays instead of empty arrays. The purpose of this post is to discuss some of the reasons why its a good practice to return empty arrays over null arrays, including Collection objects or typed array.

Null Pointer Exception

Consider the reusability of the following code:

public List getItems() {
   ...
   // There are no items, return null
   return null;
}

Let’s say you want to iterate on the results, the following code would throw a NullPointerException if used in conjunction with the code above:

List items = getItems();
for(int i=0; i<items.size(); i++) {
   // If there are no items, this code will throw a null pointer
}

Iterating on an array is one of the most commons practices in Java, so returning null instead of an empty array means the person is going to have to do extra null checks when they really don’t need to. In this situation, an empty array would suffice and would not produce any errors.

To summarize, it makes the code shorter, easier to read, and less likely to throw a NullPointerException. Also, there is some confusion with returning null since you may (or may not) be saying an empty array is the same thing as null. For example, the following would be confusing logic:

List items = getItems();
if(items == null) {
   // If null do one thing
} else if(items.size==0) {
   // If empty do another?
}

In this situation its not clear why you might act differently on the two return values and this can lead to confusing, ambiguous code.

The only time I might consider returning null valid is if there was an error of some kind, but then you should be throwing an exception (something more programmers are hesitant to do). Think of it like this, would you rather read a stack trace with a detailed error what went wrong in the code created by you, or would you rather see NullPointerException and wonder what of a dozen objects might have been null?