私はとコールバックListenableFuture
を使ったパターンに慣れています。onSuccess()
onFailure()
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
ListenableFuture<String> future = service.submit(...)
Futures.addCallback(future, new FutureCallback<String>() {
public void onSuccess(String result) {
handleResult(result);
}
public void onFailure(Throwable t) {
log.error("Unexpected error", t);
}
})
Java 8CompletableFuture
は、多かれ少なかれ同じユースケースを処理することを意図しているようです。単純に、上記の例を次のように翻訳し始めることができます。
CompletableFuture<String> future = CompletableFuture<String>.supplyAsync(...)
.thenAccept(this::handleResult)
.exceptionally((t) -> log.error("Unexpected error", t));
これは確かにバージョンよりも冗長ではなく、ListenableFuture
非常に有望に見えます。
ただし、 をとらないため、コンパイルされませexceptionally()
ん。この場合は.Consumer<Throwable>
Function<Throwable, ? extends T>
Function<Throwable, ? extends String>
これは、単にエラーをログに記録することはできず、エラーの場合に返す値を考え出す必要がString
あり、エラーの場合に返す意味のある値がないことを意味String
します。null
コードをコンパイルするためだけに、を返すことができます。
.exceptionally((t) -> {
log.error("Unexpected error", t);
return null; // hope this is ignored
});
しかし、これは再び冗長になり始めており、冗長性を超えて、それが浮かんでいるのは好きではありません.null
誰かがその値を取得またはキャプチャしようとする可能性があり、かなり後の時点で予期しNullPointerException
ない
もし私が少なくともこのようなことをexceptionally()
することができたなら -Function<Throwable, Supplier<T>>
.exceptionally((t) -> {
log.error("Unexpected error", t);
return () -> {
throw new IllegalStateException("why are you invoking this?");
}
});
--しかし、そうではありません。
exceptionally()
が有効な値を生成してはならない場合、どうするのが正しいでしょうか? このユースケースをより適切にサポートするために、私ができることCompletableFuture
、または新しい Java 8 ライブラリーで他にできることはありますか?