4 回答

TA貢獻1860條經(jīng)驗 獲得超8個贊
正如@Ole 所說, Optional 并不意味著:
與其創(chuàng)建一個 Optional,不如創(chuàng)建一個單例流(我剛剛注意到 Stream::of 的存在)。
您失去了 Optional::map 僅在元素存在時執(zhí)行的便利性,因此您自己有過濾器空值:
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.
如果您從可選開始,您可以執(zhí)行以下操作:
Optional<A> optA;
Stream.of(optA.orElse(null))
stream 到 optional 的過渡是平滑的,而 optional 到 stream 則不是。

TA貢獻1866條經(jīng)驗 獲得超5個贊
你不應(yīng)該使用這樣的結(jié)構(gòu)有兩個原因:
首先,你不應(yīng)該混搭
null
andOptional
。Optional
真的是null
api-wise 的替代品。當你返回時null
,你就有問題了。A::getB
應(yīng)該返回一個Optional<B>
,而不是一個null
。好的,有時您可以從外部世界獲取 API,而您沒有動手A::getB
,所以如果是這種情況,您只需像這樣工作,但另一種方法是清理您的輸入。其次,您不應(yīng)該記錄
null
值。如果你記錄null
值,這意味著你有類似的問題NullPointerExceptions
,這意味著你沒有得到你所期望的。所以這基本上意味著你應(yīng)該清理你的輸入!在開發(fā)的時候有這種語句是可以的,但是在生產(chǎn)中,你應(yīng)該能夠在a.getB()
返回null和b.getC()
返回null時區(qū)別對待。這些天來,使用調(diào)試器通常比使用那些關(guān)于哪個值是null
.
這兩個問題都可以通過清理您的輸入來解決。清理您的輸入意味著您應(yīng)該將不屬于您的輸入映射到您的輸入。通常的答案是代碼重復(fù):API 代碼和您的代碼。嗯,是的:有 API 模型和你的模型,但它不是重復(fù)的代碼:一個被清理,另一個沒有!
但無論如何,使用簡單的包裝器完全可以實現(xiàn)您的期望。實際上,它與您編寫的內(nèi)容相似(即使您沒有顯示代碼),但我想您已經(jīng)找到了處理此問題的最佳方法:
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條經(jīng)驗 獲得超6個贊
您可以與返回一些默認值Optional.orElseGet()的 a 一起使用(不確定我的類型是否完全正確)。Supplier<A>A
Supplier<A> nonNullASupplier = () -> {
LOGGER.log("Invoking supplier because A was null");
return new A();
}
然后在調(diào)用代碼中:
Optional.ofNullable(a)
.orElseGet(nonNullASupplier)
.map(A::getB)
.map(B::getC)
.ifPresent(c -> ...) // do something with c
同樣不是 100% 確定這里有什么類型A,B但這是基本思想。

TA貢獻1853條經(jīng)驗 獲得超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)
添加回答
舉報