8

I have seen code where almost every variable in all application layers is checked for not being null. I have also seen code almost without this.

if(object != null){}

What are the best practices for checking if a variable is NULL? Where does it really make sense, and is getting a NullPointerException really a bad thing - is all this null checking maybe a symptom that your application is in poor health?

rsp
  • 23,135
  • 6
  • 55
  • 69

4 Answers4

8

It is a good idea to check for null explicitly because:

  • You can catch the error earlier.
  • You can provide a more descriptive error message.

If you get a NullPointerException you might not be able to work out exactly which variable was null. Even if you have the line number where the exception was thrown, there might still be more than one variable on that line.

It's particularly important to put these checks in your public interface. This is because when your user provides an incorrect parameter they should get an IllegalArgumentException telling them that they made an error. If they just get back a NullPointerException they can't tell if they provided an incorrect parameter, or if there is just a bug in your code.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • Exactly. I wish the runtime would use the local variable table (if it is present) and some sort of method invocation history to give a better `NullPointerException` message. In the meantime, explicit null checking is a helpful substitute. – erickson Dec 01 '11 at 19:44
  • 1
    But according to **Effective Java, 2nd Edition by Joshua Bloch - Item 60**: "If a caller passes `null` in some parameter for which null values are prohibited, convention dictates that `NullPointerException` be thrown rather than `IllegalArgumentException`." – KrishPrabakar Jun 15 '12 at 06:47
3

Here are some of the best practices in the order of importance:

  1. Don't return a null if you can help it. For example, if your method returns a collection, return an empty collection rather than a null. In some instances the Null Object pattern can be of help. But you have to be careful to only use it where the NullObject can offer a reasonable default behavior without an additional if-check.
  2. Check for nulls if your code can offer a reasonable handling of null cases. If you simply throw another exception upon detecting a null, there is little value in handling the null explicitly.
  3. Document all instances of a function returning nulls in the function's javadoc. (unfortunately, you can't really rely on the javadoc, but it help in maintaining discipline).
Dmitry B.
  • 9,107
  • 3
  • 43
  • 64
  • Good stuff. As well as javadoc for nulls using the JSR-305 / FindBugs annotations is a good habit for return values and parameters: http://findbugs.sourceforge.net/manual/annotations.html – Russ Hayward Dec 02 '11 at 00:00
0

NullPointerExceptions are a pain. They arise from looking for items in collections (caches, maps, list, databases, filesystems... the list goes on) and assigning nulls to variables or accessing them.

Filesystems have a good approach to failed references -- FileNotFoundException -- Except, this gets clouded in with IOException, so it's not so visible and useful.

I've found that having these *NotFound exceptions extending from Exception are super useful and extensive use of them have eliminated most all of my NPEs.

When I search my database or lookup a key from a cache, my finders typically throw a NotFound variant and in my code, I know where I could have an empty value that would normally disrupt my code, and now I have a place where I can log it or deal with it.

try{
    Record r = table.where(F_ID+"=?",id);
    r.doStuff();
}catch(RecordNotFoundException e){
    LOG.info("whoops - id " + id + " not found?",e);
}

For smaller things like arrays or maps, check length or existence before you check for nulls .

if(map.contains(id)){
    map.get(id).doStuff();
}else{
    LOG.info("whoops - id " + id + " not found?",e);
}

if(arr.length < index && arr[index] != null){
    arr[index].doStuff();
}else{
    LOG.info("whoops - index " + index + " not found?",e);
}

The other place they come from is from bad instantiation like "Long id = null" and then references to id as if it were not -- This is just plain bad coding, you should not initialize it if you are just going to set it to null. Usually this is done so that the developer can search/evaluate a situation, and then set the value -- But if your searches throw NotFound's and your existence checks are in if blocks, your logical elements should prevent you from accessing a null value -- Because you would have to directly assign it.

Because NPE's are typically from bad searches, and that there are ways to circumvent these failures that incorporate good coding practices, that null checks are sometimes considered bad habit.

The best way to avoid NPE's is to never allow a null to be assigned with good coding habits.

So my answer is: you check for nulls if you are working on bad code. You just have to. But if it's all your code, you should never be returning nulls or assigning them.

Nthalk
  • 3,774
  • 1
  • 25
  • 19
-2

Variables should be initialised when defined, e.g.

Object myObject = new Object();

not

Object myObject;
... // other code that might use myObject
myObject = new Object();

This will eliminate most cases of an object potentially being null. For other cases where an object may be null, checking it is in order, but that does not mean you have to check every single variable.

Gigi
  • 28,163
  • 29
  • 106
  • 188
  • 5
    A blank declaration (one where no value is assigned) is a great way to avoid null checks; the compiler will not allow the variable to be read until a value is assigned, so you can't check it for `null` or attempt to de-reference it. In fact, developers feeling as if they have to initialize every variable leads to assigning `null` (instead of a valid value), which encourages null-checking and `NullPointerExceptions`. Either use a blank declaration, or don't declare until you provide a valid initialization. – erickson Dec 01 '11 at 19:42