第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何處理 Java 可選鏈中空值的日志記錄

如何處理 Java 可選鏈中空值的日志記錄

哆啦的時光機 2022-11-02 15:20:26
假設(shè)我正在使用選項,并且我有:A a;....Optional.ofNullable(a)    .map(A::getB)    .map(B::getC)    .ifPresent(c -> ...) // do something with c但是,如果出于某種原因,我想在 B::getC 為空(或 a 為空)時記錄。有一些成語來處理這個問題嗎?我可以做一堆嵌套的 ifPresent 調(diào)用,但這非常冗長。我能想到的最好的方法是一個 FunctionalHelper 類,它包裝了一些 Optional 方法并添加了其他方法來支持日志記錄(log4j):private static final Logger LOG = //...private static final FunctionalHelper FH     = new FunctionalHelper(LOG, Level.DEBUG);FH.ofNullable(a, Level.WARN, "You gave me a null A"))    .map(FH.logNull(A::getB, "b was null for a: {}", a-> FH.args(a.getName()))    .map(B::getC)    .ifPresent(c -> ...) // do something with c它有效,但感覺有點像一個螺栓固定的解決方案。是否有一些成語(或至少是標準庫)來處理這種事情?(我也想知道如何干凈地處理鏈中拋出的檢查異常,但也許這是一個單獨的問題。)更新:作為對@Ole VV 的回應(yīng),這里是可選的示例(更新2:我對其進行了一些調(diào)整以匹配 log4j varags 供應(yīng)商語義,但具有功能:private static final FunctionalHelper FH  = new FunctionalHelper(LOG, Level.DEBUG);void foo(A someA) {    FH.ofNullable(someA, Level.WARN, "You gave me a null A")            .map(FH.logNull(A::getB, "B was null for A: {}", A::getName))            .map(FH.logNull(B::getC, "C was null for B: {}", B::getName))            .ifPresent(c -> { /* do something with c */});}這是一個 If-else 實現(xiàn):void foo2(A a) {    if (a == null) LOG.debug("You gave me a null A");    else {        B b = a.getB();        if (b == null) LOG.debug("B was null for a: {}", a::getName);        else {            String c = b.getC();            if (c == null) LOG.debug("C was null for a: {}", b::getName);            else { /* do something with c */ }        }    }}我會說前者更容易閱讀。也更容易修改現(xiàn)有的可選鏈以在需要時添加一些東西。
查看完整描述

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 則不是。


查看完整回答
反對 回復(fù) 2022-11-02
?
心有法竹

TA貢獻1866條經(jīng)驗 獲得超5個贊

你不應(yīng)該使用這樣的結(jié)構(gòu)有兩個原因:

  1. 首先,你不應(yīng)該混搭nulland Optional。Optional真的是nullapi-wise 的替代品。當你返回時null,你就有問題了。A::getB應(yīng)該返回一個Optional<B>,而不是一個null。好的,有時您可以從外部世界獲取 API,而您沒有動手A::getB,所以如果是這種情況,您只需像這樣工作,但另一種方法是清理您的輸入。

  2. 其次,您不應(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 -> ...)


查看完整回答
反對 回復(fù) 2022-11-02
?
慕勒3428872

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但這是基本思想。


查看完整回答
反對 回復(fù) 2022-11-02
?
暮色呼如

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)


查看完整回答
反對 回復(fù) 2022-11-02
  • 4 回答
  • 0 關(guān)注
  • 166 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號