views:

87

answers:

6

Hi.

Let's say I'd like to perform the following command:

house.getFloor(0).getWall(WEST).getDoor().getDoorknob();

To avoid a NullPointerException, I'd have to do the following if:

if (house != null && house.getFloor(0) && house.getFloor(0).getWall(WEST) != null
  && house.getFloor(0).getWall(WEST).getDoor() != null) ...

Is there a way or an already existing Utils class that does this more elegantly, let's say something like the following?

checkForNull(house.getFloor(0).getWall(WEST).getDoor().getDoorknob());
+1  A: 

How about try catch around it?

try
{
  house.getFloor(0).getWall(WEST).getDoor().getDoorknob();
}
catch (NullPointerException e)
{
  //something
}
Itay
don't catch NPE
Bozho
A: 

No, only thing that You can is to insert that code in try catch block, and catch that exception.

try
{
  house.getFloor(0).getWall(WEST).getDoor().getDoorknob();
}
catch (NullPointerException e)
{

}

But this is not recommended solution.

Vash
noo, don't catch NullPointerException
Bozho
Please don't do this...
Justin Ardini
This is very bad practice...
f1sh
+4  A: 

You could of course simply wrap the whole expression up in a try-catch block, but that's a bad idea. Something cleaner is the Null Object pattern. With that, if your house doesn't have floor 0, it just returns a Floor that acts like a regular Floor, but has no real content; Floors, when asked for Walls they don't have, return similar "Null" Walls, etc, down the line.

Carl Manaster
But if a wall doesn't have a door, then returning null is the logical thing to do. Otherwise you will require methods like hasDoor() to know that there is no actual door, since you are just going to get a fake one when you ask for it.
Robin
@Robin, it's not *exactly* a "fake" wall. It's the wall that isn't, that doesn't exist. And (unlike null) it behaves like a real wall, so it's useful in ways that null can't be.
Carl Manaster
Using the Null Object pattern is a good option if you don't care whether in the end something will happen or not (+1 for that)
Bozho
So basically, you convert a "fail fast" NPE into a "maybe fail at an unspecified later time and place"? There are some cases where null objects make sense (empty collections, most prominently), but IMO they're totally unfit as a general replacement for null.
Michael Borgwardt
No, I expect there to be a wall, but not necessarily a door (to get picky). I was describing the problem with this approach in the particular example since not all walls will contain doors and the ability to determine if there is a door is made more complicated with the Null Object pattern. @Michael Borgwardt describes the issue in the general sense in his comment. My experience has been that this pattern is rather limited in the applications to which it can be applied.
Robin
+4  A: 

The best way would be to avoid the chain. If you aren't familiar with the Law of Demeter (LoD), in my opinion you should. You've given a perfect example of a message chain that is overly intimate with classes that it has no business knowing anything about.

Law of Demeter: http://en.wikipedia.org/wiki/Law_of_Demeter

Jerod Houghtelling
+3  A: 

Make sure things that can't logically be null are not. For example - a house always has a West wall. In order to avoid such exceptions in state, you can have methods to check whether the state you expect is present:

if (wall.hasDoor()) {
   wall.getDoor().etc();
}

This is essentially a null-check, but might not always be.

The point is that you should do something in case you have a null. For example - return or throw an IllegalStateException

And what you shouldn't do - don't catch NullPointerException. Runtime exceptions are not for catching - it is not expected that you can recover from them, nor it is a good practice to rely on exceptions for the logic flow. Imagine that you actually don't expect something to be null, and you catch (and log) a NullPointerException. This will not be very useful information, since many things can be null at that point.

Bozho
+1  A: 

There is no checkForNull method that you can write that will facilitate this (that's simply not how method invokation and argument evaluation works in Java).

You can break down the chained statements into multiple statements, checking at every step. However, perhaps a better solution is to not have these methods return null in the first place. There is something called the Null Object Pattern that you may want to use instead.

Related questions

polygenelubricants