[英]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
安全導航操作員正在使用。 如果engine
為null
,則整個表達式將計算為null
。
此解決方案適用於Java 6。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.