Java 已检查lambda表达式中引发的异常

Java 已检查lambda表达式中引发的异常,java,exception-handling,lambda,java-8,checked-exceptions,Java,Exception Handling,Lambda,Java 8,Checked Exceptions,您能解释一下为什么必须从lambda表达式中捕获选中的异常吗?换句话说,为什么下面的代码不编译 public void doSomething(ObjectInputStream istream) throws IOException { // The read method throws an IOException. IntStream.range(0, 10).forEach(i -> someList.add(read(istream))); } 但是这个会吗 publi

您能解释一下为什么必须从lambda表达式中捕获选中的异常吗?换句话说,为什么下面的代码不编译

public void doSomething(ObjectInputStream istream) throws IOException {
  // The read method throws an IOException.
  IntStream.range(0, 10).forEach(i -> someList.add(read(istream)));
}
但是这个会吗

public void doSomething(ObjectInputStream istream) throws IOException {
  IntStream.range(0, 10).forEach(i -> {
    try {
      // The read method throws an IOException.
      someList.add(read(istream));
    }
    catch (IOException ioe) {
      // Callee has to handle checked exception, not caller.
    }
  });
}

似乎被调用方现在必须处理抛出的任何已检查异常,而不是调用方。

问题不是lambda表达式,而是它正在实现的接口。记住,lambda表达式基本上只是实现给定接口的匿名类的简写

在本例中,
forEach
接受
java.util.function.Consumer

公共接口使用者{
无效接受(T);
...
}

请注意,
accept
未声明为抛出任何内容。这意味着它的任何实现都不能抛出任何东西;不是命名类,不是匿名类,也不是lambda。

您的
read
方法似乎抛出了
IOException

IntStream.forEach
的签名是,其中
IntConsumer
有一个
void-accept(int-value)
方法。在这种情况下,lambda表达式
i->someList.add(read(istream))
相当于:

public class IntConsumerImplementation implements IntConsumer {
   ObjectInputStream istream;
   public void accept(int i) {
      someList.add(read(istream));
   };
}
它不会编译,因为
read
抛出一个选中的异常

另一方面,如果函数接口定义了lambda表达式,那么lambda表达式可能会抛出选中的异常(这对于使用者或其他
java.util
函数接口来说是而不是

假设下面是一个虚构的示例:

 @FunctionalInterface
 public interface NotAnIntConsumer {
    public void accept(int i) throws IOException;
 }
现在汇编如下:

forEach(NotAnIntConsumer naic) { ... }
doSomething(ObjectInputStream istream) throws IOException {
   IntStream.range(0, 10).forEach(i -> someList.add(read(istream)));
}
forEach(NotAnIntConsumer naic) { ... }
doSomething(ObjectInputStream istream) throws IOException {
   IntStream.range(0, 10).forEach(i -> someList.add(read(istream)));
}