问题描述
我想在访问几个类深的字段(在get方法链中)时检查空指针。
但是,如果其中一个早期方法为null
,则无论如何都会得到NullPointerException
。
这是我想要检查的,虽然它仍然可以获得NullPointerException
:
if(x.getLocation().getBuilding().getSolidFuelInd() != null)
pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");
这是我希望上面的代码展示的行为:
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");
pol上的字段是可选的,只有在上面的getter不为null
时才应设置。
但是构建和位置对象也可以为null
,所以现在我必须检查它们是否有效。
是否有任何一种较短的方式来检查我想要的所有内容?
1楼
如果您希望减少代码,则可以将每个调用保存在变量中。
// 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");
这更清洁,更容易遵循。
回味无穷,你不检查null
的基本类型boolean, int, byte
等。所以最后null
的检查building.getSolidFuelInd()
不需要
2楼
Java 8具有Optional<T>
,它可以生成一个链式表达式,尽管详细。
但是Java 8也有Stream<T>
,你可以有一个0或1项的“流”,然后用lambdas查询。
x.getLocation()
.map((loc) -> loc.getBuilding())
.map((building) -> building.getSolidFuelInd() != null)
.findFirst()
.ifPresent ...
要么
x.getLocation()
.map(Location::getBuilding)
.map(Building::getSolidFuelInd())
.filter(fuelInd -> fuelId != null)
.findFirst()
.ifPresent ...
应用这些新术语可能会缓慢达成协议。
3楼
使用Java 8的Optional<>
类,您可以map
一个值,如下所示:
Optional.of(x)
.map(ClassOfX::getLocation)
.map(Location::getBuilding)
.map(Building::getSolidFuelInd)
.map(solidFuelInd -> solidFuelInd ? "Y" : "N")
.ifPresent(pol::setWood_heat_ind);
只有当optional的值不为null
时,才会执行map
调用,从而避免NullPointerException
。
ifPresent
的目的是仅在值(如果可用)时调用setWood_heat_ind
。
一个很好的单调用,相当于null检查。
4楼
你可以抓住异常
try{
pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");
}catch(NullPointerException e){
//e.printStackTrace(); or whatever you want
}
(参考你可能的解决方案)检查返回值意味着多次调用相同的方法,这就是为什么我会使用这个解决方案。
正如Jay Harris指出的那样,您可以显然检查值并保存返回参数,而无需再次调用相同的方法。 您可以通过多种方式实现,其中一种方式
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");
但是这值得吗?
我让它比故意更复杂,但无论如何,为什么这样做,如果你可以try...catch
两条简单的线条?