使用CompletableFuture抛出检查异常 [英] Throwing checked exceptions with CompletableFuture

查看:3019
本文介绍了使用CompletableFuture抛出检查异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Stackoverflow包含多个有关将检查的异常与CompletableFuture混合的问题.

Stackoverflow contains multiple questions about mixing checked exceptions with CompletableFuture.

以下是一些示例:

  • Checked exception with CompletableFuture
  • Java 8 Supplier Exception handling
  • JDK8 CompletableFuture.supplyAsync how to deal with interruptedException

虽然某些答案暗示使用CompletableFuture.completeExceptionally(),但它们的方法会导致难以阅读的用户代码.

While some of answers hint at the use of CompletableFuture.completeExceptionally() their approach results in user code that is difficult to read.

我将使用此空间提供替代解决方案,以提高可读性.

I will use this space to provide an alternate solution that results in improved readability.

请注意,此问题特定于CompletableFuture.这使我们能够提供不更广泛地扩展到lambda表达式的解决方案.

Please note that this question is specific to CompletableFuture. This allows us to provide solutions that do not extend to lambda expressions more generally.

推荐答案

鉴于Completions实用工具类(下面提供),用户可以无缝地抛出检查后的异常:

Given the Completions utility class (provided below) users can throw checked exceptions seamlessly:

public CompletionStage<String> readLine()
{
  return Completions.supplyAsync(() ->
  {
    try (BufferedReader br = new BufferedReader(new FileReader("test.txt")))
    {
      return br.readLine();
    }
  });
}

由lambda引发的任何异常(无论是否选中)都将包裹在CompletionException中,这与CompletableFuture对于未检查的异常的行为一致.

Any exceptions thrown by the lambda (checked or not) will be wrapped in a CompletionException, which is consistent with CompletableFuture's behavior for unchecked exceptions.

对于像thenApply()这样的中间步骤,事情会变得有些丑陋,但这还不是世界末日:

Things get a bit uglier for intermediate steps like thenApply() but it's not the end of the world:

public CompletionStage<String> transformLine()
{
  return readLine().thenApply(line ->
    Completions.wrapExceptions(() ->
    {
      if (line.contains("%"))
        throw new IOException("Lines may not contain '%': " + line);
      return "transformed: " + line;
    }));
}

以下是Completions实用工具类中的一些方法.您可以通过这种方式包装其他CompletableFuture方法.

Here some methods from the Completions utility class. You can wrap other CompletableFuture methods this way.

/**
 * Helper functions for {@code CompletionStage}.
 *
 * @author Gili Tzabari
 */
public final class Completions
{
    /**
     * Returns a {@code CompletionStage} that is completed with the value or exception of the {@code CompletionStage}
     * returned by {@code callable} using the supplied {@code executor}. If {@code callable} throws an exception the
     * returned {@code CompletionStage} is completed with it.
     *
     * @param <T>      the type of value returned by {@code callable}
     * @param callable returns a value
     * @param executor the executor that will run {@code callable}
     * @return the value returned by {@code callable}
     */
    public static <T> CompletionStage<T> supplyAsync(Callable<T> callable, Executor executor)
    {
        return CompletableFuture.supplyAsync(() -> wrapExceptions(callable), executor);
    }

    /**
     * Wraps or replaces exceptions thrown by an operation with {@code CompletionException}.
     * <p>
     * If the exception is designed to wrap other exceptions, such as {@code ExecutionException}, its underlying cause is wrapped; otherwise the
     * top-level exception is wrapped.
     *
     * @param <T>      the type of value returned by the callable
     * @param callable an operation that returns a value
     * @return the value returned by the callable
     * @throws CompletionException if the callable throws any exceptions
     */
    public static <T> T wrapExceptions(Callable<T> callable)
    {
        try
        {
            return callable.call();
        }
        catch (CompletionException e)
        {
            // Avoid wrapping
            throw e;
        }
        catch (ExecutionException e)
        {
            throw new CompletionException(e.getCause());
        }
        catch (Throwable e)
        {
            throw new CompletionException(e);
        }
    }

    /**
     * Returns a {@code CompletionStage} that is completed with the value or exception of the {@code CompletionStage}
     * returned by {@code callable} using the default executor. If {@code callable} throws an exception the returned
     * {@code CompletionStage} is completed with it.
     *
     * @param <T>      the type of value returned by the {@code callable}
     * @param callable returns a value
     * @return the value returned by {@code callable}
     */
    public static <T> CompletionStage<T> supplyAsync(Callable<T> callable)
    {
        return CompletableFuture.supplyAsync(() -> wrapExceptions(callable));
    }

    /**
     * Prevent construction.
     */
    private Completions()
    {}
}

这篇关于使用CompletableFuture抛出检查异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆