2015-12-11 7 views
21

CompletableFutureを返す非同期メソッドを記述したいと思います。将来の唯一の目的は、メソッドが完了した時点を追跡することであり、結果は追跡しないことです。 CompletableFuture<Void>またはCompletableFuture<?>を返す方が良いでしょうか?どちらか一方を好む理由はありますか、それともそれらは交換可能ですか?Return CompletableFuture <Void>またはCompletableFuture <?>?

  • CompletableFutureは、多くの方法からCompletableFuture<Void>を返します。
  • java.nioは、AsynchronousSocketChannelFuture<Void> connect(SocketAddress remote)Future<Void>を有する。 とScheduledExecutorServiceリターンFuture<?>のような一方
  • java.util.concurrentクラス:例えば、 Future<?> submit(Runnable task)と。

私は、パラメータリスト、変数宣言、またはその他のコンテキストではなく、戻り値の型についてのみ尋ねることに注意してください。

+1

私は将来がであることがわかります。将来は未来のものであると明示的に述べています。将来のは未知の未来だと言います。 –

+3

Java 6 to Java 7の変更点、[ここ](http://stackoverflow.com/a/12962219/438154)を参照してください。 –

答えて

6

CompletableFuture<Void>を使用することをお勧めします。

According to this answerは、Sotirios Delimanolisによって見つけられました。Future<?>は、小さなAPIの欠陥です。 Java 6では、submit()メソッドはFuture<Object>を内部的に使用していたため、戻り値の型はFuture<?>に設定されていました。 Java 7では、実装は内部でFuture<Void>を使用するように変更されましたが、戻り値がFuture<?>のままになるようにAPIを変更するには遅すぎました。

新しいJava APIでは、Future<Void>CompletableFuture<Void>が使用されます。それらは我々が従うべき例である。

12

<ボイド>または CompletableFuture < CompletableFutureを返す方が良いでしょうか? >

いずれかの理由がありますか、または は互換性がありますか?

コードが影響を与える可能性があり3つのコンテキストがあります。

  • ランタイム - ジェネリックは、それには何の意味を持っていません。
  • コンパイル - 何らかの方法がFuture<Void>を受け入れるが、Future<?>を受け入れないケースは想像できません。
  • 開発 - Futureの結果に意味がない場合は、そのことについて、宣言を通じてユーザーに伝えることをお勧めします。

従ってFuture<Void>がより好ましい。あなたは(それが存在しないため)CompletableFuture<Void>が結果を得ることができない方法での副作用の種類で使用されていることがわかりますCompletableFuture APIを見てみると

7

、例:

CompletableFuture.runAsync(Runnable runnable); 

返しますCompletableFuture<Object>ここでは結果が実際にはないので混乱するでしょう、我々は完了を気にします。 ConsumersRunnablesを受け取るメソッドは、CompletableFuture<Void>、例:thenAcceptthenAcceptAsyncを返します。 ConsumerおよびRunnableは、一般的な副作用に使用されます。

Voidの別の使用例は、本当に結果がわからない場合です。たとえば、CompletableFuture.allOfの場合、渡されたリストはRunnableから生成されたCompletableFutureである可能性があります。結果は取得できません。

CompletableFuture<Void>は、別のオプションがない場合にのみ有効です。結果を返すことができれば、それに行くようにしてください。興味のない場合は、発信者が破棄することもできます。 CompletableFuture<Void>は仕事をしますが、CompletableFuture<T>がオプションであり、決して結果が必要ではないと判断した場合はAPIユーザーがあなたを嫌に思うでしょう。

3

適切なタイプは意味に依存します。リストされたすべてのオプションは、完了を通知することを約束し、例外を非同期的に返すことがあります。

  • CompletableFuture<Void>Voidは、予想される結果がないことをユーザに伝えます。
  • ?は、任意の値を配信できるという意味でcontains値の型が定義されていないことを意味します。

CompletableFutureクラスはいくつかの便利なメソッドをCompletionStageから継承しています。しかし、あなたのメソッドの呼び出し元が未来の完了をトリガーできるようにもなります。これは、あなたのメソッドが完了自体を知らせる責任があるためです。 cancel(...)メソッドもあります。これは、実行をキャンセルしないので、CompletableFutureのデフォルト実装ではかなり無意味です。

  • Future<Void>Voidを期待すべき結果がないユーザーに伝えます。
  • Future<?>?は、任意の値を配信できるという意味でcontains値の型が定義されていないことを意味します。

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>を継承するインターフェイスを自分で作成することをお勧めします。

呼び出し元が将来の完了をトリガーする可能性があるため、宣言された戻り値タイプCompletableFutureでの戻りは避けてください。意図的にコードを混乱させると驚くほどハングすることになります。これは、どのコードが完了をトリガーするのかがはっきりしないためです。型システムが意図しない完了をトリガーするのを防ぐには、上記のより限定された型のうちの1つを使用します。

関連する問題