[英]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.