Checking Java NullPointerException over chained methods

I want to check for a null pointer when accessing a field of multiple classes in depth (in a chain of get methods). However, if one of the previous methods null

, I get a NullPointerException

anyway.

This is what I want to test, although it can still get NullPointerException

:

if(x.getLocation().getBuilding().getSolidFuelInd() != null)
            pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");

      

This is the behavior I want to show above:

if(x.getLocation() != null)
    if(x.getLocation().getBuilding() != null)
        if(x.getLocation().getBuilding().getSolidFuelInd() != null)
            pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");

      

The pol field is optional and should only be set if the above user is irrelevant null

. However, building and location objects can also be null

, so now I have to check that they are valid.

Is there some shorter way to test all of the above as I want?

+3


source to share


4 answers


If you want to shrink it, you can store each call in a variable.

// note: Replace type with the correct type
type location = x.getLocation();
type building = location == null ? null : location.getBuilding();

// note: you don't have to check for null on primitive types 
pol.setWood_heat_ind(building != null && building.getSolidFuelInd() ? "Y" : "N");

      



It's much cleaner and easier to follow.

Food for thought, you don't check null

for primitive types boolean, int, byte

etc., so the last null

check building.getSolidFuelInd()

is unnecessary

+2


source


Java 8 has Optional<T>

that will do for a single related expression, albeit verbose.

However Java 8 also has Stream<T>

, and you could have a "stream" of 0 or 1 item and then a request with lambdas.

x.getLocation()
    .map((loc) -> loc.getBuilding())
    .map((building) -> building.getSolidFuelInd() != null)
    .findFirst()
    .ifPresent ...

      



or

x.getLocation()
    .map(Location::getBuilding)
    .map(Building::getSolidFuelInd())
    .filter(fuelInd -> fuelId != null)
    .findFirst()
    .ifPresent ...

      

It will likely be a slow transition to conditions using these new terms.

+1


source


You can just catch the exception

    try{
        pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");
    }catch(NullPointerException e){
        //e.printStackTrace(); or whatever you want
    }

      

(Referring to your possible solution) checking the return values ​​means using the same methods once at the same time, so I would use this solution.

As Jay Harris pointed out, you can obviously check the values ​​and keep the return parameter without having to call the same method again. You can do it in different ways, here is one

    Object loc=null,build=null;

    Boolean SFI = ((loc=x.getLocation())==null?null:
                   ((build=loc.getBuilding())==null?null:
                       (build.getSolidFuelInd())));

    if(SFI!=null)pol.setWood_heat_ind(SFI?"Y":"N");

      

But is it worth it? I made it harder than it was possible, but anyway, why do it if you can try...catch

in two simple lines?

0


source


You can shorten this very little by combining the conditions into one test:

if (x.getLocation() != null 
&& x.getLocation().getBuilding() != null 
&& x.getLocation().getBuilding().getSolidFuelInd() != null) {
    pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");
}

      

but otherwise no, it's about as short as it gets.

Catching an exception can be too broad if something in the implementation of one of these getters changes and calls NPE, after which it can be caught and eventually hide the proof of the error. The use of if tests is more deliberate and more deliberate.

Jay's version is good too, +1 from me. But this can lead to a simple check. And his code does not leave the property Wood_heat_ind

null if any of the x fields is null.

0


source







All Articles