Thursday, August 7, 2008

Avoid NPE when comparing strings

By now everyone knows that you should use the equals method when comparing two objects in Java (as opposed to using the == operator). Strings are no different. But what happens when you compare a null reference to a string literal, like so:
String myRef = null;if ( myRef.equals("literal") ) {    // do something}

If you run this code you'll see you get a Null Pointer Exception for calling a method on a null reference. I've seen some developers get around this problem by checking for null before calling equals.
String myRef = null;if ( myRef != null && myRef.equals("literal") ) {    // do something}

This cleverly uses the short-circuit property of the && operator. If the first part of the condition is false the second part won't be evaluated, avoiding the NPE. Like most clever code, this is not the best way to go about it. I learned a better way when reviewing a colleague's code. Just take the original condition and switch it around so you call equals on the literal, and pass the (possibly null) reference as a parameter.
String myRef = null;if ( "literal".equals(myRef) ) {    // do something}

This avoids the NPE because a string literal can never be null. If the reference is null, the condition returns false, as expected. This solution is also a little bit shorter and clearer than the first one. The lesson to be learned here is that if you have to resort to "clever" tricks to get something done, with just a little bit of lateral thinking you can probably find a cleaner, simpler way.

Johannes Rössel said...

Interestingly, this mirrors (though for other reasons) the habit C programmers had for putting the literal first in comparisons:

if (5 == a) {
...
}

In C this was primarily because compilers don't tend to warn you about mistyping == as = and assignment to a literal is never going to be valid.

That being said, I still find literal first comparisons a little hard to read since in my mind, I'm comparing a variable to something I know, not something I know to a variable. It can easily be reversed, surely but it's not the order in which many people tend to think, I guess.

Bill the Lizard said...

Johannes,
Yes, those two idioms are very closely related.

I've heard a surprising number of developers complain that they trip over the strangeness of the literal-first syntax. Luckily, we shouldn't have to worry much about it any more. Any modern compiler should warn you if you accidentally type in

if(a = 5) {
...
}