BJ *_*ruz 6 java lambda exception-handling checked-exceptions java-8
你能解释为什么必须从lambda表达式中捕获检查异常吗?换句话说,为什么以下代码无法编译...
public void doSomething(ObjectInputStream istream) throws IOException {
// The read method throws an IOException.
IntStream.range(0, 10).forEach(i -> someList.add(read(istream)));
}
Run Code Online (Sandbox Code Playgroud)
但是这个会吗?
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.
}
});
}
Run Code Online (Sandbox Code Playgroud)
看起来被调用者现在必须处理被抛出的任何已检查异常而不是调用者.
问题不在于lambda表达式,而是它正在实现的接口.请记住,lambda表达式基本上只是实现给定接口的匿名类的简写.
在这种情况下,forEach需要java.util.function.Consumer<T>:
public interface Consumer<T> {
void accept(T t);
...
}
Run Code Online (Sandbox Code Playgroud)
请注意,accept未声明抛出任何内容.这意味着没有任何实现可以抛出任何东西; 不是命名类,不是匿名类,不是lambda.
似乎你的read方法抛出了IOException.
签名IntStream.forEach是forEach(IntConsumer action),哪里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));
};
}
Run Code Online (Sandbox Code Playgroud)
因为read抛出已检查的异常而无法编译.
另一方面,如果函数接口定义了lambda表达式,则lambda表达式可能抛出已检查的异常(消费者或其他功能接口不是这种情况java.util).
假设以下组成示例:
@FunctionalInterface
public interface NotAnIntConsumer {
public void accept(int i) throws IOException;
}
Run Code Online (Sandbox Code Playgroud)
现在以下编译:
forEach(NotAnIntConsumer naic) { ... }
doSomething(ObjectInputStream istream) throws IOException {
IntStream.range(0, 10).forEach(i -> someList.add(read(istream)));
}
Run Code Online (Sandbox Code Playgroud)