【问题标题】:Why doesn't Lambda understand throws in method signature? [duplicate]为什么 Lambda 不理解方法签名中的抛出? [复制]
【发布时间】:2022-02-10 21:54:40
【问题描述】:

在下面的代码中,我在方法签名中编写了 throws,但在 Lambda 中再次为 write 编写,编译器给出了错误。为什么?

编译器错误:未处理的异常:java.io.IOException

 public void saveTodoItems() throws IOException {

    try (BufferedWriter outputStream = new BufferedWriter(new OutputStreamWriter(
            new FileOutputStream("TodoItems.txt"), StandardCharsets.UTF_8))) {

        todoItems.forEach(todoItem -> {
                outputStream.write(todoItem.getShortDescription() + "\t" //compile error on write
                        + todoItem.getDetail() + "\t"
                        + todoItem.getDeadLine()+"\n");

        });
    }
}

【问题讨论】:

  • 什么是todoItems?某种清单?还有什么错误?
  • @byxor 是的,它是一个数组列表,编译器错误是:未处理的异常:java.io.IOException
  • IOException 是“检查异常”。无论您使用 lambda 实现了什么接口,它都不会声明该方法将引发 IOException。您可能需要在 lambda 中使用 try/catch
  • @byxor "Whatever interface you've implemented" 它是 Iterable 的 forEach,所以它只是 java.util.function.Consumer。
  • 这里只使用常规的for循环。

标签: java exception lambda


【解决方案1】:

请记住,lambda 应该是函数式接口的实现。在这种情况下,forEach 将功能接口Consumer<T> 作为参数。

void forEach(Consumer<? super T> action)

所以你的 lambda 实际上是在 Consumer 接口中实现单个抽象方法 - accept。此方法未声明抛出任何异常:

void accept(T t); // no throws clause here at all!

因此,write 调用可能抛出的IOException 被视为未处理。您在saveTodoItems 方法中添加了throws 子句这一事实无关紧要。

另一方面,如果您声明了自己的函数式接口,并且在其单个抽象方法中确实包含 throws 子句:

interface IOConsumer<T> {
    void accept(T t) throws IOException;
}

可以这样写:

IOConsumer<TodoItem> consumer = todoItem -> {
    outputStream.write(todoItem.getShortDescription() + "\t"
                    + todoItem.getDetail() + "\t"
                    + todoItem.getDeadLine()+"\n");
};

当然,您不能在forEach 中使用它,因为它只接受Consumer,而不接受IOConsumer。您应该在 write 周围加上 try...catch,或查看 here 了解更多替代方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多