我想在访问几个类深的字段(在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
,所以现在我必须检查它们是否有效。
是否有任何一种较短的方式可以像我想的那样检查上述所有内容?
答案 0 :(得分:2)
如果您希望减少代码,则可以将每个调用保存在变量中。
// 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()
次检查
答案 1 :(得分:1)
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 ...
应用这些新条款可能会缓慢达成协议。
答案 2 :(得分:1)
使用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);
map
调用仅在可选参数的值不是null
时执行,从而避免使用NullPointerException
。
ifPresent
的目的是仅在有可用值时调用您的setWood_heat_ind
。
一个不错的单次调用,等效于空检查。
答案 3 :(得分:0)
你可以抓住异常
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
可以用两个简单的行?