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?
source to share
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
source to share
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.
source to share
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?
source to share
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.
source to share