CompletableFuture鏈?zhǔn)秸{(diào)用中exceptionally()和handle()的用法區(qū)別是什么?

completablefuture的exceptionally()僅處理異常并返回默認(rèn)值,handle()則同時處理結(jié)果和異常并可轉(zhuǎn)換結(jié)果。1.exceptionally()適用于僅需異常時提供備用值的場景,如緩存或數(shù)據(jù)庫失敗后返回默認(rèn)數(shù)據(jù);2.handle()適用于需統(tǒng)一處理成功與異常情況的場景,如記錄日志、轉(zhuǎn)換結(jié)果或根據(jù)異常返回不同信息;3.在鏈?zhǔn)秸{(diào)用中,可先用exceptionally()設(shè)置默認(rèn)值,再用handle()進行最終處理,從而實現(xiàn)組合式錯誤管理。

CompletableFuture鏈?zhǔn)秸{(diào)用中exceptionally()和handle()的用法區(qū)別是什么?

CompletableFuture的exceptionally()和handle()都是用來處理異步操作中的異常情況的,但它們在處理方式和返回值上有所不同。簡單來說,exceptionally()只處理異常情況,并返回一個備用值;而handle()則可以處理正常結(jié)果和異常,并允許你轉(zhuǎn)換結(jié)果。

CompletableFuture鏈?zhǔn)秸{(diào)用中exceptionally()和handle()的用法區(qū)別是什么?

exceptionally() vs handle()

CompletableFuture鏈?zhǔn)秸{(diào)用中exceptionally()和handle()的用法區(qū)別是什么?

exceptionally()方法主要用于提供一個在發(fā)生異常時使用的備用值。如果CompletableFuture正常完成,exceptionally()會被跳過。

handle()方法則更通用。它接收一個BiFunction,該函數(shù)接收兩個參數(shù):異步操作的結(jié)果和拋出的異常。無論CompletableFuture是正常完成還是拋出異常,handle()都會被調(diào)用。

CompletableFuture鏈?zhǔn)秸{(diào)用中exceptionally()和handle()的用法區(qū)別是什么?

CompletableFuture鏈?zhǔn)秸{(diào)用中的應(yīng)用

在鏈?zhǔn)秸{(diào)用中,選擇使用哪個方法取決于你的需求。如果僅僅需要在出現(xiàn)異常時提供一個默認(rèn)值,那么exceptionally()就足夠了。如果需要更復(fù)雜的邏輯,例如記錄日志、轉(zhuǎn)換異常、或者根據(jù)異常類型返回不同的值,那么handle()會更合適。

如何選擇?

  • 僅處理異常,提供備用值? 使用exceptionally()。
  • 需要處理正常結(jié)果和異常,并進行轉(zhuǎn)換? 使用handle()。
  • 需要在出現(xiàn)異常時記錄日志? 使用handle()。

exceptionally()的適用場景及示例

exceptionally()最適合于那些你只想在出現(xiàn)異常時提供一個默認(rèn)值,而不想關(guān)心正常結(jié)果的情況。例如,從緩存中獲取數(shù)據(jù),如果緩存中沒有,則嘗試從數(shù)據(jù)庫中獲取,如果數(shù)據(jù)庫也失敗了,則返回一個默認(rèn)值。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {     // 模擬從數(shù)據(jù)庫獲取數(shù)據(jù),可能拋出異常     if (Math.random() < 0.5) {         throw new RuntimeException("數(shù)據(jù)庫連接失敗");     }     return "數(shù)據(jù)庫數(shù)據(jù)"; }).exceptionally(e -> {     System.err.println("發(fā)生異常: " + e.getMessage());     return "默認(rèn)數(shù)據(jù)"; // 返回默認(rèn)值 });  future.thenAccept(result -> System.out.println("結(jié)果: " + result));

在這個例子中,如果supplyAsync()中的代碼拋出異常,exceptionally()會捕獲這個異常,打印錯誤信息,并返回一個默認(rèn)值”默認(rèn)數(shù)據(jù)”。

handle()的適用場景及示例

handle()的適用場景更廣泛,因為它允許你同時處理正常結(jié)果和異常。例如,你可能需要在操作成功時記錄成功日志,在操作失敗時記錄失敗日志,并根據(jù)異常類型返回不同的錯誤信息。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {     // 模擬api調(diào)用,可能拋出異常     if (Math.random() < 0.5) {         throw new RuntimeException("API調(diào)用失敗");     }     return "API數(shù)據(jù)"; }).handle((result, ex) -> {     if (ex != null) {         System.err.println("發(fā)生異常: " + ex.getMessage());         return "錯誤: " + ex.getMessage(); // 根據(jù)異常返回錯誤信息     } else {         System.out.println("API調(diào)用成功");         return result; // 返回正常結(jié)果     } });  future.thenAccept(result -> System.out.println("結(jié)果: " + result));

在這個例子中,handle()方法接收兩個參數(shù):API調(diào)用的結(jié)果和可能出現(xiàn)的異常。如果API調(diào)用成功,handle()會打印成功日志并返回API數(shù)據(jù)。如果API調(diào)用失敗,handle()會打印錯誤信息并返回一個包含錯誤信息的字符串

鏈?zhǔn)秸{(diào)用中的組合使用

在復(fù)雜的鏈?zhǔn)秸{(diào)用中,可以同時使用exceptionally()和handle()來處理不同的異常情況。例如,可以使用exceptionally()提供一個默認(rèn)值,然后使用handle()來記錄日志或進行更復(fù)雜的錯誤處理。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {     // 模擬操作,可能拋出異常     if (Math.random() < 0.5) {         throw new RuntimeException("操作失敗");     }     return "操作結(jié)果"; }).exceptionally(e -> {     System.err.println("發(fā)生異常: " + e.getMessage());     return "默認(rèn)結(jié)果"; }).handle((result, ex) -> {     if (ex != null) {         System.err.println("最終處理異常: " + ex.getMessage());         return "最終錯誤結(jié)果";     } else {         System.out.println("最終處理成功");         return result;     } });  future.thenAccept(result -> System.out.println("最終結(jié)果: " + result));

在這個例子中,如果supplyAsync()拋出異常,exceptionally()會返回一個默認(rèn)結(jié)果。然后,handle()會接收到這個默認(rèn)結(jié)果,并打印成功日志。如果在exceptionally()中也拋出了異常(雖然不太可能),handle()會捕獲這個異常并返回一個最終錯誤結(jié)果。

總而言之,選擇exceptionally()還是handle()取決于你的具體需求。如果只需要提供一個備用值,exceptionally()更簡單。如果需要更復(fù)雜的錯誤處理邏輯,handle()更靈活。

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊10 分享