Нет необходимости в такой конструкции, как
try {
return helper(c);
}catch(Throwable th) {
throw th;
}
, поскольку поведение по отлову и повторному выбрасыванию исключения не отличается от того, чтобы не перехватить исключение в первую очередь. Аналогично, цепочка .exceptionally(ex -> { throw ex; }
была бы бессмысленной, если бы она была законной. (Это не так, поскольку Throwable
является проверенным исключением.
Если помощник не выбрасывает проверенные исключения, вы можете просто использовать CompletableFuture.supplyAsync(() -> helper(c))
. В противном случае вы должны заключить проверенные исключения в непроверенные исключения;самый естественный выбор здесь будет CompletionException
.
Это будет выглядеть следующим образом:
List<CompletableFuture<MyObject>> futures = class_list.stream()
.map(c -> CompletableFuture.supplyAsync(() ->
try {
return helper(c);
} catch(Throwable th) {
throw new CompletionException(th);
}
))
.collect(Collectors.toList());
Ваша вторая операция тихая небрежно. Имя класса CompletionException
, а не Completionexception
Далее, выброс существующего исключения, хранящегося в переменной ex
, выполняется с помощью throw ex;
, а не throw new ex;
. Но, как уже было сказано, когда вы хотите, чтобы исключение было (пере) выброшено, просто не перехватывайте егопервое место.
Проблема в том, что get
выбрасывает проверенный ExecutionException
, а не непроверенный CompletionException
. Для последнего вы должны использовать join
. Таким образом, вы можете достичь желаемого результата. -бросок через
// will throw when any future completed exceptionally
futures.forEach(CompletableFuture::join);