问题
The question is rather simple: I'm looking for an elegant way of using CompletableFuture#exceptionally
alongside with CompletableFuture#supplyAsync
. This is what does not work:
private void doesNotCompile() {
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(() -> throwSomething())
.exceptionally(Throwable::getMessage);
}
private String throwSomething() throws Exception {
throw new Exception();
}
I thought the idea behind exceptionally()
was precisely to handle cases where an Exception
is thrown. Yet if I do this it works:
private void compiles() {
CompletableFuture<String> thisIsFine = CompletableFuture.supplyAsync(() -> {
try {
throwSomething();
return "";
} catch (Exception e) {
throw new RuntimeException(e);
}
}).exceptionally(Throwable::getMessage);
}
I could work with that, but it looks horrible and makes things harder to maintain. Is there not a way to keep this clean which doesn't require transforming all the Exception
into RuntimeException
?
回答1:
This might not be a super popular library, but we use it (and from times to times I do some work there too; minor though) internally: NoException. It is really, really nicely written for my taste. This is not the only thing it has, but definitely covers your use case:
Here is a sample:
import com.machinezoo.noexception.Exceptions;
import java.util.concurrent.CompletableFuture;
public class SO64937499 {
public static void main(String[] args) {
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(Exceptions.sneak().supplier(SO64937499::throwSomething))
.exceptionally(Throwable::getMessage);
}
private static String throwSomething() throws Exception {
throw new Exception();
}
}
Or you can create these on your own:
final class CheckedSupplier<T> implements Supplier<T> {
private final SupplierThatThrows<T> supplier;
CheckedSupplier(SupplierThatThrows<T> supplier) {
this.supplier = supplier;
}
@Override
public T get() {
try {
return supplier.get();
} catch (Throwable exception) {
throw new RuntimeException(exception);
}
}
}
@FunctionalInterface
interface SupplierThatThrows<T> {
T get() throws Throwable;
}
And usage:
CompletableFuture<String> sad = CompletableFuture
.supplyAsync(new CheckedSupplier<>(SO64937499::throwSomething))
.exceptionally(Throwable::getMessage);
来源:https://stackoverflow.com/questions/64937499/letting-completablefuture-exceptionally-handle-a-supplyasync-exception