为什么我不能在 Java 8 lambda 表达式中引发异常?

2022-08-31 22:26:07

我升级到Java 8,并尝试用新的lambda表达式替换Map的简单迭代。该循环搜索 null 值,如果找到异常,则引发异常。旧的 Java 7 代码如下所示:

for (Map.Entry<String, String> entry : myMap.entrySet()) {
    if(entry.getValue() == null) {
        throw new MyException("Key '" + entry.getKey() + "' not found!");
    }
}

我试图将其转换为Java 8,如下所示:

myMap.forEach((k,v) -> {
    if(v == null) {
        // OK
        System.out.println("Key '" + k+ "' not found!");

        // NOK! Unhandled exception type!
        throw new MyException("Key '" + k + "' not found!");
    }
});

谁能解释一下为什么这里不允许这种说法,以及如何纠正这一点?throw

Eclipse的快速修复建议在我看来并不合适...它只是用一个块将语句括起来:throwtry-catch

myMap.forEach((k,v) -> {
    if(v == null) {
        try {
            throw new MyException("Key '" + k + "' not found!");
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
});

答案 1

不允许引发选中的异常,因为 java.util.function.BiConsumer<T, U> 接口中的 accept(T t, U u) 方法未在其子句中声明任何异常。而且,如您所知,Map#forEach采用这种类型。throws

public interface Map<K, V> {

    default void forEach(BiConsumer<? super K, ? super V> action) { ... }

}                        |
                         |
                         V
@FunctionalInterface
public interface BiConsumer<T, U> {

    void accept(T t, U u); // <-- does throw nothing

}

当我们谈论已检查的异常时,情况确实如此。但是你仍然可以抛出一个未经检查的异常(例如java.lang.IllegalArgumentException):

new HashMap<String, String>()
    .forEach((a, b) -> { throw new IllegalArgumentException(); });

答案 2

您可以在 lambda 中引发异常。

允许 lambda 引发与 lambda 实现的功能接口相同的异常。

如果函数接口的方法没有 throws 子句,则 lambda 不能引发 CheckedExceptions。(您仍然可以抛出 RuntimeExceptions)。


在您的特定情况下,使用 a 作为参数,BiConsumer 定义为:Map.forEachBiConsumer

public interface BiConsumer<T, U> {
    void accept(T t, U u);
}

此函数接口的 lambda 表达式不能引发 CheckedExceptions。


包中定义的函数接口中的方法不会引发异常,但您可以使用其他函数接口或创建自己的函数接口来引发异常,即给定此接口:java.util.function

public interface MyFunctionalInterface<T> {
    void accept(T t) throws Exception;
}

以下代码是合法的:

MyFunctionalInterface<String> f = (s)->throw new Exception("Exception thrown in lambda"); 

推荐