繁体   English   中英

在Java中检查不为空

[英]Check not null in Java

想象一下,我在Java中生成了XML生成的实体,它包含了我需要的一些数据。 例如:

<Car>
   <Engine>
      <Power>
         175
      </Power>
   </Engine>
</Car>

因此,如果我需要一个引擎电源,那么接下来是商业软件开发的最佳实践,我将做下一件事:

Car car = dao.getCar()
Power power = car != null && car.engine != null ? power : null
return power

我讨厌这个。 有时似乎有一半的代码只是空检查。

有任何想法吗?

看看Java 8 Optional类 它确实如此:它避免了对null的丑陋检查。

在您的情况下,您可以使用此代码段来避免它们:

Car car = dao.getCar();
Optional<Car> optionalCar = Optional.ofNullable(car); 
Optional<Power> optionalPower = getPowerIfPresent(optionalCar);

Power power = Optional.empty();
if(optionalPower.isPresent()) {
    power = optionalPower.get();
}

在写完一个能够返回给定car power的功能之后:

public static Optional<Power> getPowerIfPresent(Optional<Car> car) {
    return car
        .flatMap(c -> c.getEngine())
        .map(e -> e.getPower());
}

这与使用Optional相同,但可能更具可读性:

public class NullSafe<T> {
    private final T value;
    public NullSafe(@Nullable T value) { this.value = value; }
    public static <T> NullSafe<T> of(@Nullable T value) { return new NullSafe<>(value); }

    public <R> NullSafe<R> get(Function<T,R> mapper) {
        R newValue = (value != null) ? mapper.apply(value) : null;
        return new NullSafe<>(newValue);
    }

    public T nullable() { return value; }
    public T orDefault(T defaultValue) { return (value != null) ? value : defaultValue; }
}

用法:

Power power = NullSafe.of(dao.getCar())
    .get(Car::getEngine)
    .get(Engine::getPower)
    .nullable(); // .orDefault(Power.defaultPower());

替代方案可以是静态方法:

public static <R> R get(Supplier<R> supplier, R defaultValue) {
    try {  return supplier.get(); } 
    catch (NullPointerException ex) { return defaultValue; }
}

public static <R> R getNullable(Supplier<R> supplier) { return get(supplier, null); }

用法:

Power power = NullSafe.get(() -> dao.getCar().getEngine().getPower(), Power.defaultPower());
Power powerOrNull = NullSafe.getNullable(() -> dao.getCar().getEngine().getPower());

或者也许创建一些util方法:

static <T> Optional<T> tryGet(Supplier<T> getter) {
    try {
        return Optional.ofNullable(getter.get());
    } catch(NullPointerException ignored) {
        return Optional.empty();
    }
}

然后你可以像这样使用它:

System.out.println(tryGet(() -> car.engine.power).orElse(new Power()));

有一个库无例外可以做到这一点,但你不能指定它只是“沉默”NPE。

Exceptions.silence().get(() -> car.engine.power).orElse(new Power())

我现在的方法就是:

public class CarDataExtractor {

   private final Car car;

   private CarDataExtractor(Car car) {
       this.car = car;
   }

  public static CarDataExtractor on(Car car) {
       return new CarDataExtractor(car);
   }

   public EngineDataExtractor engine() {
       return car != null && car.getEngine() != null
               ? EngineDataExtractor.on(car.getEngine())
               : EngineDataExtractor.on(null);
   }

   public Car self() {
       return car;
   }
}

public class EngineDataExtractor {

   private final Engine engine;

   private EngineDataExtractor(Engine engine) {
       this.engine = engine;
   }

   public static EngineDataExtractor on(Engine engine) {
       return new EngineDataExtractor(engine);
   }

   public PowerDataExtractor engine() {
       return engine != null && engine.getPower() != null
               ? PowerDataExtractor.on(engine.getPower())
               : PowerDataExtractor.on(null);
   }

   public Engine self() {
       return engine;
   }
}

...

Power power = CarDataExtractor.on(dao.getCar()).engine().power().self()

这是因为我被限制在Java 6 ...

还有另一个选项,你可以使用,如果你使用的是Spring,它可能会对你有所帮助。

如果您不使用Spring,则需要为项目添加额外的依赖项

使用Spel你可以做到:

ExpressionParser parser = new SpelExpressionParser();

StandardEvaluationContext context = new StandardEvaluationContext(dao.getCar());

Power power = parser.parseExpression("engine?.power").getValue(context, Power.class);

在表达engine?.power安全导航操作员正在使用。 如果enginenull ,则整个表达式将计算为null

此解决方案适用于Java 6。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM