当前位置: 首页 > 知识库问答 >
问题:

为什么我不能在Java8 lambda表达式中抛出异常?[复制]

蒋招
2023-03-14

我升级到Java 8,并试图用一个新的lamdba表达式替换通过映射的简单迭代。循环搜索空值,如果找到,则抛出异常。旧的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!");
    }
});

有人能解释为什么这里不允许语句以及如何纠正这一点吗?

Eclipse的快速修复建议在我看来不太对劲......它只是用try-catch块包围语句:

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

共有2个答案

屈翰飞
2023-03-14

可以在lambdas中抛出异常。

允许lambda抛出与lambda实现的函数接口相同的异常。

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

在您的特定情况下,Map。forEach使用双余弦作为参数,双余弦定义为:

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

此函数接口的lambda表达式不能抛出CheckedExceptions。

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

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

以下代码将是合法的:

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

太叔小云
2023-03-14

不允许抛出选中的异常,因为java.util.function.BiConsumer中的方法是accept(T T,U)

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(); });
 类似资料:
  • 问题内容: 直接的答案是因为s接口被指定为不会引发异常。但是为什么呢? 或换句话说:我必须依赖可以引发异常的函数。从理论上讲,这不应该发生。但是,如果发生这种情况,我希望它脱离我正在使用的整个函数(在中)。即我希望它的行为就像发生未处理的异常一样。 似乎这不可能以一种显而易见的自然方式进行(因为如果接口说它不能抛出异常,就不会)。 我该如何解决?用丑陋的try / catch并打印出异常,并希望我

  • 问题内容: 我升级到Java 8,并尝试用新的lamdba表达式替换Map中的简单迭代。循环搜索空值,如果找到一个,则引发异常。旧的Java 7代码如下所示: 我将其转换为Java 8的尝试如下所示: 谁能解释为什么此处不允许该声明以及如何更正该声明? Eclipse的快速修复建议对我来说并不正确……它只是在语句周围加上了一个块: 问题答案: 不允许抛出检查异常,因为接口中的方法未在其子句中声明任

  • 下面是我的代码。当我运行它时,我在线程“main”java.lang.IndexOutOfBoundsException:Index:3、Size:2中得到异常,而不是我的异常消息。谁能解释一下我做错了什么,为什么会这样?谢谢!

  • 在try块中为未抛出异常子类的方法捕获异常,将无法编译。当我捕捉到异常时,它起作用了。它是如何工作的??

  • 针对每个循环处理跳过迭代的控件的问题,我发现允许在不断变化的集合上进行迭代: 例如,以下内容: 投掷 InvalidOperationException:集合已修改;枚举操作可能无法执行。 然而,在a。Net窗体,您可以执行以下操作: 它跳过元素,因为迭代器运行在更改的集合上,而不会引发异常 错误?如果基础集合发生变化,迭代器是否需要抛出? 所以我的问题是为什么对不断变化的的迭代不会抛出Inval

  • 这是我的申请 数据源:类型:com.zaxxer.hikari.HikariDataSource主要: 这是我的入门: 这是我的例外: 2017-11-21 10:10:33.126线程“main”中的表现:java.lang.运行时异常: java.lang.ClassCastException: 无法将 com.mysql.cj.jdbc.Driver to javax.sql.DataSou