Java NullPointerException检查链式方法

时间:2015-07-16 14:37:41

标签: java nullpointerexception null

我想在访问几个类深的字段(在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,所以现在我必须检查它们是否有效。

是否有任何一种较短的方式可以像我想的那样检查上述所有内容?

4 个答案:

答案 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");

这更清晰,更容易理解。

值得深思,您不会检查基本类型nullboolean, 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时执行,从而避免使用NullPointerExceptionifPresent的目的是仅在有可用值时调用您的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可以用两个简单的行?