4 回答
TA贡献1860条经验 获得超8个赞
正如@Ole 所说, Optional 并不意味着:
与其创建一个 Optional,不如创建一个单例流(我刚刚注意到 Stream::of 的存在)。
您失去了 Optional::map 仅在元素存在时执行的便利性,因此您自己有过滤器空值:
A a;
Stream.of(a)
.peek(e->{if(e == null){LOG.debug("You gave me a null A");}})
.filter(e->e != null) //Now you have to handle null values yourself
.map(A::getB)
.peek(e->{if(e == null){LOG.debug("B was null for A "+a.getName());}})
.filter(e->e != null)
.map(B::getC)
.peek(e->{if(e == null){LOG.debug("C was null for B"+a.getB().getName());}})
.filter(e->e != null)
.findFirst() // Optional from now on.
如果您从可选开始,您可以执行以下操作:
Optional<A> optA;
Stream.of(optA.orElse(null))
stream 到 optional 的过渡是平滑的,而 optional 到 stream 则不是。
TA贡献1866条经验 获得超5个赞
你不应该使用这样的结构有两个原因:
首先,你不应该混搭
null
andOptional
。Optional
真的是null
api-wise 的替代品。当你返回时null
,你就有问题了。A::getB
应该返回一个Optional<B>
,而不是一个null
。好的,有时您可以从外部世界获取 API,而您没有动手A::getB
,所以如果是这种情况,您只需像这样工作,但另一种方法是清理您的输入。其次,您不应该记录
null
值。如果你记录null
值,这意味着你有类似的问题NullPointerExceptions
,这意味着你没有得到你所期望的。所以这基本上意味着你应该清理你的输入!在开发的时候有这种语句是可以的,但是在生产中,你应该能够在a.getB()
返回null和b.getC()
返回null时区别对待。这些天来,使用调试器通常比使用那些关于哪个值是null
.
这两个问题都可以通过清理您的输入来解决。清理您的输入意味着您应该将不属于您的输入映射到您的输入。通常的答案是代码重复:API 代码和您的代码。嗯,是的:有 API 模型和你的模型,但它不是重复的代码:一个被清理,另一个没有!
但无论如何,使用简单的包装器完全可以实现您的期望。实际上,它与您编写的内容相似(即使您没有显示代码),但我想您已经找到了处理此问题的最佳方法:
static <T,U> Function<T, U> logIfReturnsNull(Function<? super T, ? extends U> function, String functionName) {
return input -> {
U result = function.apply(input);
if (result == null) {
log.debug("{} returned null for input {}", functionName, input);
}
return result;
};
}
然后你像这样使用它:
Optional.ofNullable(a)
.map(logIfReturnsNull(A::getB, "A::getB"))
.map(logIfReturnsNull(B::getC, "B::getC"))
.ifPresent(c -> ...)
TA贡献1848条经验 获得超6个赞
您可以与返回一些默认值Optional.orElseGet()的 a 一起使用(不确定我的类型是否完全正确)。Supplier<A>A
Supplier<A> nonNullASupplier = () -> {
LOGGER.log("Invoking supplier because A was null");
return new A();
}
然后在调用代码中:
Optional.ofNullable(a)
.orElseGet(nonNullASupplier)
.map(A::getB)
.map(B::getC)
.ifPresent(c -> ...) // do something with c
同样不是 100% 确定这里有什么类型A,B但这是基本思想。
TA贡献1853条经验 获得超9个赞
我不知道这是否适合你,但也许你可以使用空对象模式。
class NullA extends A {
B getB() {
return new NullB();
}
}
class NullB extends B {
C getC() {
return new NullC();
}
}
class NullC extends C {
}
然后使用orElseGet返回空对象:
Optional.ofNullable(a)
.orElseGet(new NullA())
.map(A::getB)
.map(B::getC)
添加回答
举报