从 lambda 表达式中抛出的已检查异常
Checked exceptions thrown from within lambda expressions
您能否解释一下为什么必须从 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 表达式,而在于它正在实现的接口。请记住,对于实现给定接口的匿名 class,lambda 表达式基本上只是 shorthand。
在这种情况下,forEach
需要 java.util.function.Consumer<T>
:
public interface Consumer<T> {
void accept(T t);
...
}
请注意,accept
并未声明要抛出任何东西。这意味着它的任何实现都不能抛出任何东西;不是命名 class,不是匿名 class,也不是 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));
};
}
无法编译,因为 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 表达式中捕获已检查的异常?也就是说,为什么下面的代码不能编译...
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 表达式,而在于它正在实现的接口。请记住,对于实现给定接口的匿名 class,lambda 表达式基本上只是 shorthand。
在这种情况下,forEach
需要 java.util.function.Consumer<T>
:
public interface Consumer<T> {
void accept(T t);
...
}
请注意,accept
并未声明要抛出任何东西。这意味着它的任何实现都不能抛出任何东西;不是命名 class,不是匿名 class,也不是 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));
};
}
无法编译,因为 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)));
}