Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have some code that is failing because of NullPointerException. A method is being called on the object where the object does not exist.

However, this led me to think about the best way to fix this. Do I always code defensively for nulls so that I future proof code for null pointer exceptions, or should I fix the cause of the null so that it won't occur downstream.

What are your thoughts?

share|improve this question
3  
Why would you not "fix the cause of the null"? Can you provide an example of why this isn't the only sensible choice? Clearly, something must be pushing you away from the obvious. What is it? Why isn't fix the root cause your first choice? –  S.Lott Feb 23 '11 at 19:26
    
Well fixing the "root cause" of the issue may help in the short term, but if the code is still not defensively checking for nulls and is reused by another process that may introduce a null, i would have to fix it again. –  Shaun F Feb 23 '11 at 19:33
1  
@Shaun F: If the code is broken, it's broken. I don't get how it's possible for code to produce unexpected nulls and not get fixed. Clearly, there's some "dumb management" or "political" stuff going on. Or something that allows erroneous code to be somehow acceptable. Can you explain how erroneous code is not getting fixed? What's the political background that leads you to ask this question? –  S.Lott Feb 23 '11 at 19:37
    
No it's actually much much simpler than that. There are no politics around it. There is data created and at times this can have nulls in it. I can fix the data creation routine and leave the consumer vulnerable to later data creation that had nulls in it, or i can fix the consumer, with ugly defensive code, and be assured that I could care less what happens upstream. –  Shaun F Feb 23 '11 at 20:10
    
@Shaun F If you're worried about inadequate reuse, you can add @throws NullPointerException If paramx is null to the method Javadoc comment. –  biziclop Feb 23 '11 at 20:16
show 2 more comments

9 Answers

Well if one of the possible outcomes of your method is a null value then you should code defensively for that, but if a method is supposed to return a non-null but isn't I would fix that for sure.

As usual it depends on the case, as with most things in life :)

share|improve this answer
add comment

If null is a reasonable input parameter for your method, fix the method. If not, fix the caller. "Reasonable" is a flexible term, so I propose the following test: How should the method hande a null input? If you find more than one possible answer, then null is not a reasonable input.

share|improve this answer
1  
It's really as simple as that. –  biziclop Feb 23 '11 at 20:17
2  
Guava has some very nice helper methods making the null check as simple as Precondition.checkNotNull(...). See stackoverflow.com/questions/3022319/… –  user1249 Feb 23 '11 at 21:18
    
My rule is to initialize everything to sensible defaults if possible and worry about null exceptions afterwards. –  davidk01 Feb 24 '11 at 1:00
    
Thorbjørn: So it replaces an accidental NullPointerException with an intentional NullPointerException? In some cases, doing the early check might be useful or even necessary; but I fear lots of senseless boilerplate null checks that add little value and just make the program larger. –  user281377 Feb 24 '11 at 8:45
2  
If null is not a reasonable input parameter to your method but calls of the method are likely to accidentally pass null (especially if the method is public), you may also want to have your method throw an IllegalArgumentException when given null. This signals to callers of the method that the bug is in their code (rather than in the method itself). –  Brian Aug 5 '13 at 19:06
add comment

I would recommend fixing the method to be defensive. For instance:

String go(String s){  
    return s.toString();  
}

Should be more along the lines of this:

String go(String s){  
    if(s == null){  
       return "";  
    }     
    return s.toString();  
}

I realize this is absolutely trivial, but if the invoker expects an object give them a default object that won't cause a null to be passed around.

share|improve this answer
    
+1 That's something I've never thought about, and certainly has merit. –  Michael K Feb 23 '11 at 19:45
8  
This has a nasty side-effect in that the caller (programmer who codes against this API) might develop a habit of passing null as a parameter to get "default" behavior. –  Goran Jovic Feb 23 '11 at 20:07
    
@Goran Correct, that is why one must be careful when creating an API you only get one shot to get it right –  Woot4Moo Feb 23 '11 at 20:10
2  
If this is Java, you shouldn't be using new String() at all. –  biziclop Feb 23 '11 at 20:14
1  
@biziclop actually it is far more important than most realize. –  Woot4Moo Feb 23 '11 at 21:01
show 9 more comments

There are multiple ways to handle this, peppering your code with if (obj != null) {} is not ideal, it is messy, it adds noise when reading the code later during the maintenance cycle and is error prone, as it is easy to forget to do this boiler plate wrapping.

It depends on if you want the code to continue executing quietly or fail. Is the null an error or an expected condition.

What is null

In every defintion and case, Null represents the absolute lack of data. Nulls in databases represent the lack of a value for that column. a null String is not the same as an empty String, a null int is not the same thing as ZERO, in theory. In practice "it depends". Empty String can make a good Null Object implementation for the String class, for Integer it depends on the business logic.

Alternatives are:

  1. The Null Object pattern. Create an instance of your object that represents the null state, and initialize all references to that type with a reference to the Null implementation. This is useful for simple value type objects that don't have a lot of references to other objects that could also be null and is expected to be null as a valid state.

  2. Use Aspect Oriented tools to weave methods with a Null Checker aspect that prevents the parameters from being null. This is for cases where null is an error.

  3. Use assert() not much better than the if (obj != null){} but less noise.

  4. Use a Contract Enforcement tool such as Contracts For Java. Same use case as something like AspectJ but newer and uses Annotations instead of external configuration files. Best of both works of Aspects and Asserts.

1 is the ideal solution when incoming data is known to be null and needs to be replaced with some default value so that upstream consumers won't have to deal with all the null checking boilerplate code. Checking against known default values will be more expressive as well.

2, 3, and 4 are just convenient alternative Exception generators to replace NullPointerException with something more informative, which is always and improvement.

In the End

null in Java is almost in all cases a logic error. You should always strive to eliminate the root cause of NullPointerExceptions. You should strive to not use null conditions as business logic. if (x == null) { i = someDefault; } just make the initial assigment to that default object instance.

share|improve this answer
    
If possible the null object pattern is the way to, it is the most graceful way to handle a null case. It's rare that you want a null to cause stuff to blow up in production! –  Richard Miskin Feb 23 '11 at 21:34
    
@Richard: unless that null is unexpected then it is a true error, then everything should come to a complete halt. –  Jarrod Roberson Feb 23 '11 at 22:24
add comment

tl;dr - it is GOOD to check for unexpected nulls but BAD for an application to try to make them good.

Details

Clearly, there are situations where null is a valid input or output to a method, and others where it is not.

Rule #1:

The javadoc for a method that allows a null parameter or returns a null value must clearly document this, and explain what the null means.

Rule #2:

An API method should not be specified as accepting or returning null unless there is a good reason to do so.

Given a clear specification of a method's "contract" vis-a-vis nulls, it is a programming error to pass or return a null where you shouldn't.

Rule #3:

An application should not attempt to "make good" programming errors.

If a method detects a null that shouldn't be there, it should not attempt to fix the problem by turning it into something else. That just hides the problem from the programmer. Instead, it should allow the NPE to happen, and cause a failure so that the programmer can figure out what the root cause is and fix it. Hopefully the failure will be noticed during testing. If not, that says something about your testing methodology.

Rule #4:

Where feasible, write your code to detect programming errors early.

If you've got bugs in your code that result in lots of NPEs, the hardest thing can be figuring out where the null values came from. One way to make diagnosis easier is to write your code so that the null is detected as soon as possible. Often you can do this in conjunction with other checks; e.g.

public setName(String name) {
    // This also detects `null` as an (intended) side-effect
    if (name.length() == 0) {
        throw new IllegalArgumentException("empty name");
    }
}

(There are obviously cases where rules 3 and 4 should be tempered with reality. For instance (rule 3), some kinds of applications must attempt to continue after detecting probably programming errors. And (rule 4) too much checking for bad parameters can have a performance impact.)

share|improve this answer
add comment

Apache Commons' lang libraries provide a way to handle null values

the method defaultIfNull in the class ObjectUtils enables you to return a default value if the object passed is null

share|improve this answer
add comment

The following general rules about null have helped me a lot so far :

  1. If the data comes from outside your control, systematically check for nulls and act appropriately. This means either throwing an exception that makes sense to the function (checked or unchecked, just make sure the name of the exception tells you exactly what is going on.). But NEVER lest a value loose in your system that can potentially carry surprises.

  2. If Null is within the domain of appropriate values for your data model, deal with it appropriately.

  3. When returning values try to not return nulls whenever possible. Always prefer Empty lists, empty strings, Null Object patterns. Keep nulls as returned values when this is the best possible representation of data for a given use case.

  4. Probably the most important of all... Tests, tests and test again. When testing your code do not test it as a coder test it as a Nazi psychopath dominatrix and try to imagine all sorts of ways to torture the hell out of that code.

This tends a bit on the paranoid side regarding nulls often leading to façades and proxies that interface systems to the outside world and strictly controlled values in the inside with abundant redundancy. The outside world here means pretty much everything I did not code myself. It does bear a cost runtime but so far I rarely had to optimize this by creating "null safe sections" of code. I must say though that I mostly create long running systems for health care and the last thing I want is the interface subsystem carrying your iodine allergies to the CT scanner crashes because of an unexpected null pointer because someone else in another system never realized that names could contain apostrophes or characters like 但耒耨。

anyways.... my 2 cents

share|improve this answer
add comment

Adding null checks may make testing problematic. See this great lecture ...

Check out Google Tech talks lecture: "The Clean Code Talks - Don't Look For Things!" he talks about it around minute 24

http://www.youtube.com/watch?v=RlfLCWKxHJ0&list=PL693EFD059797C21E

Paranoid programming involves adding null checks everywhere. Seems like a good idea at first however from a testing perspective, it makes your null check type testing hard to deal with.

Also, when you create a precondition for the existence of some object such as

class House(Door door){

    .. null check here and throw exception if Door is NULL
    this.door = door
}

it prevents you from creating House since you will be throwing an exception. Assume your test cases are creating mock objects for testing something other than Door, well, you can't do this because door is required

Those who have suffered through Mock creation hell are well aware of these types of annoyances.

In summary, your test suite should be robust enough to test for Doors, Houses ,Roofs or whatever without having to be paranoid about it. Seroiusly, how difficult is it to add a null check test for specific objects in your testing :)

You should always prefer applications that work because you have several tests that PROVE it works, rather than HOPING it works simply because you have a whole bunch of preconditional null checks all over the place

share|improve this answer
add comment

I would propose using Option/Some/None pattern from functional languages. I am not a Java specialist, but I intensively use my own implementation of this pattern in my C# project, and I am sure it could be converted into Java world.

The idea behind this pattern is: if it is logically to have situation when there is possibility of absense of a value (for example when retreiving from database by id) you provide an object of type Option[T], where T is a possible value. I case of absense of a value object of class None[T] returned, in case if existence of the value - object of Some[T] returned, containing the value.

In this case, you must handle possibility of value absence, and if you do code review you could easily found placec of incorrect handling. To get an inspiration from C# language implementation refer to my bitbucket repository https://bitbucket.org/mikegirkin/optionsomenone

If you return a null value, and it is logically equivalent an to error (for example no file exists, or could not connect) you should throw an exception, or use another error-handling pattern. The idea behind this, again, you end up with solution, when you must handle the situation of value absence, and could easily find the places of incorrect handling in the code.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.