簡體   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