处理 lambda 中的已检查异常 [重复]

Posted

技术标签:

【中文标题】处理 lambda 中的已检查异常 [重复]【英文标题】:Handle checked exception in lambda [duplicate] 【发布时间】: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 但是如何以一种好的方式做到这一点?难道就不能让异常在层层中冒泡,直到它最终处理吗? 检查的异常在处理之前不能冒泡。每个中间方法都必须声明它。 【参考方案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))));

【讨论】:

以上是关于处理 lambda 中的已检查异常 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

从 lambda 表达式中抛出的已检查异常

如何处理 lambda 表达式中的异常 [重复]

了解 Java 中的已检查与未检查异常

从lambda抛出异常[重复]

从lambda抛出异常[重复]

如何检查异常中的哪些消息[重复]