【问题标题】:Handle checked exception in lambda [duplicate]处理 lambda 中的已检查异常 [重复]
【发布时间】:2020-05-20 09:08:26
【问题描述】:

我有一些代码会引发检查异常。我想在 lambda 中调用该代码,以便从另一个地图创建地图:

Map<String, Coordinate> map = getMap();
Map<String, Integer> result = map.entrySet().stream().collect(
    toMap(x -> x.getKey(), x -> doSomething(x.getValue)));

其中doSometing 是引发异常的代码:

int doSomething(Coordinate c) throws MyException { ... }

现在编译器肯定会抱怨没有处理异常。所以我用try-catch包围它,看起来很丑:

Map<String, Integer> result = map.entrySet().stream().collect(
    toMap(x -> x.getKey(), x -> {
        try {
            return doSomething(x.getValue());
        } catch (MyException e) {
            e.printStackTrace();
            // return some error-code here???
        }
    }));

这也不能编译,因为我们需要在catch-case 中返回一些东西。然而,在这种特殊情况下,在这里返回任何东西没有多大意义,这就是为什么我实际上不想在那个级别处理异常。我不能只处理我的调用代码中的异常,我在哪里创建 lambda?所以说只是上一层?

try {
    Map<String, Integer> result = ...
} catch (MyException e) { ... }

但这并不能编译,因为从 lambda 抛出的异常没有得到处理。

【问题讨论】:

  • 这里的问题是,你为什么要使用检查异常。另外,我相信在 labdas 中处理已检查异常的标准方法(如果你不能让它运行时)是在 lamda 中捕获它并重新抛出一个未检查的异常 - 你可以使用已检查的异常作为原因。
  • @Worthless 不幸的是,doSomething 是一个 3rd-party-API,只是抛出。
  • 那么是的,重新抛出可能是最简单的处理方法。
  • @Worthless 但是如何以一种好的方式做到这一点?难道就不能让异常在层层中冒泡,直到它最终处理吗?
  • 检查的异常在处理之前不能冒泡。每个中间方法都必须声明它。

标签: java exception lambda


【解决方案1】:

来自Baeldung's blog:你可以定义可以抛出Exception的消费者:

@FunctionalInterface
public interface ThrowingConsumer<T, E extends Exception> {
    void accept(T t) throws E;
}

和一个静态包装器将检查的异常映射到RuntimeException

static <T> Consumer<T> throwingConsumerWrapper(
  ThrowingConsumer<T, Exception> throwingConsumer) {

    return i -> {
        try {
            throwingConsumer.accept(i);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    };
}

那么你就可以调用它了:

Map<String, Integer> result = map.entrySet().stream()
    .collect(
        throwingConsumerWrapper(toMap(x -> x.getKey(), x -> doSomething(x.getValue)))
    );

【讨论】:

  • 我已经找到了这个,但我无法让 toMap 工作,因为我刚刚包装了 x -&gt; doSomething 部分。谢谢你的回答。
【解决方案2】:

过滤你的价值观是最值得的。如果您有可能引发异常的值。

然后您可以使用一种流行的包装器(即jooq.lambda)或编写自己的包装器

 map.entrySet().stream()
    .filter(x -> makeSureNoExtection(x))
    .collect(toMap(x -> x.getKey(), unchecked(x -> doSomething(x.getValue))));

【讨论】:

    猜你喜欢
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多