当前位置: 代码迷 >> java >> Java NullPointerException检查链式方法
  详细解决方案

Java NullPointerException检查链式方法

热度:119   发布时间:2023-07-31 10:56:06.0

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

是否有任何一种较短的方式来检查我想要的所有内容?

如果您希望减少代码,则可以将每个调用保存在变量中。

// 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()不需要

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 ...

应用这些新术语可能会缓慢达成协议。

使用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检查。

你可以抓住异常

    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两条简单的线条?

  相关解决方案