[英]CompletionStage, CompletableFuture Void - what to return?
[英]Return CompletableFuture<Void> or CompletableFuture<?>?
我想編寫一個返回CompletableFuture
的異步方法。 未來的唯一目的是追蹤方法何時完成,而不是結果。 返回CompletableFuture<Void>
或CompletableFuture<?>
會更好CompletableFuture<?>
? 有理由偏愛其中一個,還是可以互換?
CompletableFuture
本身從其許多方法返回CompletableFuture<Void>
。 java.nio
在AsynchronousSocketChannel
有一個Future<Void>
: Future<Void> connect(SocketAddress remote)
。 ExecutorService
和ScheduledExecutorService
這樣的java.util.concurrent
類返回Future<?>
:例如,使用Future<?> submit(Runnable task)
。 請注意,我只詢問返回類型,而不是參數列表,變量聲明或其他上下文。
最好使用CompletableFuture<Void>
。
根據 Sotirios Delimanolis發現的這個答案 , Future<?>
是一個小的API漏洞。 在Java 6中, submit()
方法在內部使用了Future<Object>
,因此其返回類型設置為Future<?>
。 在Java 7中,實現在內部更改為使用Future<Void>
,但是更改API為時已晚,因此返回值仍為Future<?>
。
較新的Java API使用Future<Void>
和CompletableFuture<Void>
。 這些是我們應該遵循的例子。
返回CompletableFuture <Void>或CompletableFuture <?>會更好嗎?
有理由偏愛其中一個,還是可以互換?
代碼可能會影響三種上下文:
Future<Void>
但不接受Future<?>
。 Future
的結果沒有意義,那么通過聲明向用戶說明這一點是一個好習慣。 所以Future<Void>
是更優選的。
查看CompletableFuture
API,您會發現CompletableFuture<Void>
與副作用一起使用無法獲得結果的方法(因為它不存在),例如:
CompletableFuture.runAsync(Runnable runnable);
返回一個CompletableFuture<Object>
會讓人感到困惑,因為沒有真正的結果,我們只關心完成。 使用Consumers
和Runnables
返回CompletableFuture<Void>
,例如: thenAccept
, thenAcceptAsync
。 Consumer
和Runnable
通常用於副作用。
Void
另一個用例是當你真的不知道結果時。 例如: CompletableFuture.allOf
,傳遞的列表可能是源自Runnable的CompletableFuture,因此我們無法獲得結果。
說完所有這些, CompletableFuture<Void>
只有在你沒有其他選擇的情況下才有用,如果你可以返回結果然后請去它,如果他們不感興趣,調用者可能會選擇丟棄。 你說你只對完成感興趣,然后是的, CompletableFuture<Void>
會完成這項工作,但是如果他們知道CompletableFuture<T>
是一個選項並且你只是代表他們決定他們的API用戶會討厭你永遠不會需要結果。
合適的類型取決於其語義。 所有列出的選項都承諾信號完成,並可能異步返回異常。
CompletableFuture<Void>
: Void
告訴用戶沒有預期的結果。 CompletableFuture<?>
?
表示包含值的類型在任何值都可以傳遞的意義上是未定義的。 CompletableFuture
類從CompletionStage
繼承了幾個便捷方法。 但是它也允許你的方法的調用者觸發未來的完成,這似乎是錯誤的,因為你的方法負責發出它自己的完成信號。 還有一個cancel(...)
方法在CompletableFuture
的默認實現中毫無意義,因為它不會取消執行。
Future<Void>
: Void
告訴用戶沒有預期的結果。 Future<?>
?
表示包含值的類型在任何值都可以傳遞的意義上是未定義的。 Future
缺乏CompletionStage
的便捷方法。 它不允許觸發未來的完成,但可以取消執行。
下一個選項是CompletionStage<Void>
:
CompletionStage<Void>
: Void
告訴用戶沒有預期的結果。 存在綁定處理程序的便捷方法,但cancel(...)
方法不存在。 方法的調用者無法觸發CompletionStage
。 <CancellableFuture extends Future<Void> & CompletionStage<Void>>
:來自Future<Void>
和CompletionStage<Void>
。 它告訴沒有結果,存在便利方法以及取消選項。 方法的調用者無法觸發CompletionStage
。 缺少cancel(...)
方法可能適合您的情況。 因此,如果您不需要取消,我建議使用CompletionStage<Void>
如果您需要取消執行選項,請使用<CancellableFuture extends Future<Void> & CompletionStage<Void>>
。 如果您選擇<CancellableFuture extends Future<Void> & CompletionStage<Void>>
您可能想要自己創建一個繼承Future<Void>
和CompletionStage<Void>
的接口作為返回類型而不是直接放置long類型的交集在您的方法聲明中。
您應該避免使用聲明的返回類型CompletableFuture
返回,因為調用者可能會觸發將來的完成。 故意這樣做會導致令人困惑的代碼和令人驚訝的掛起,因為不清楚哪個代碼負責觸發完成。 使用上述更受限制的類型之一讓類型系統防止方法調用者觸發意外完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.