从 lambda 表达式中抛出的已检查异常
Posted
技术标签:
【中文标题】从 lambda 表达式中抛出的已检查异常【英文标题】:Checked exceptions thrown from within lambda expressions 【发布时间】:2015-04-26 18:18:46 【问题描述】:您能否解释一下为什么必须从 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.
);
现在似乎被调用者必须处理所有抛出的检查异常,而不是调用者。
【问题讨论】:
【参考方案1】:问题不在于 lambda 表达式,而在于它正在实现的接口。请记住,lambda 表达式基本上只是实现给定接口的匿名类的简写。
在这种情况下,forEach
采用 java.util.function.Consumer<T>
:
public interface Consumer<T>
void accept(T t);
...
请注意,accept
未被声明为抛出任何东西。这意味着它的任何实现都不会抛出任何东西;不是命名类,不是匿名类,也不是 lambda。
【讨论】:
【参考方案2】:您的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));
;
因为read
抛出了一个已检查的异常而无法编译。
另一方面,如果函数式接口定义了 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)));
【讨论】:
以上是关于从 lambda 表达式中抛出的已检查异常的主要内容,如果未能解决你的问题,请参考以下文章