假设我有一个类和一个方法
class A {
void foo() throws Exception() {
...
}
}
现在我想调用foo的每个实例的A交付的流,如:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
问:如何正确地处理异常?代码不能在我的机器上编译,因为我没有处理可能由foo()抛出的异常。bar的抛出异常在这里似乎毫无用处。为什么呢?
更易读的方式:
class A {
void foo() throws MyException() {
...
}
}
只需要将它隐藏在RuntimeException中,让它通过forEach()
void bar() throws MyException {
Stream<A> as = ...
try {
as.forEach(a -> {
try {
a.foo();
} catch(MyException e) {
throw new RuntimeException(e);
}
});
} catch(RuntimeException e) {
throw (MyException) e.getCause();
}
}
虽然在这一点上,如果有人说跳过流并使用for循环,我不会反对,除非:
你没有使用Collection.stream()创建流,也就是说,没有直接转换为for循环。
你正在尝试使用parallelstream()
这个问题可能有点老了,但因为我认为这里的“正确”答案只有一种方式,这可能会导致一些问题隐藏在您的代码后面。即使有一点争议,受控异常的存在也是有原因的。
在我看来,你能找到的最优雅的方法是Misha在这里给出的聚合Java 8流中的运行时异常
通过在“期货”中执行操作。因此,您可以运行所有工作的部分,并将不工作的异常作为单个异常收集。否则,您可以将它们全部收集到一个List中,稍后再处理它们。
本吉·韦伯(Benji Weber)也提出了类似的方法。他建议创建一个自己的类型来收集工作和不工作的部分。
根据您真正想要实现的输入值和输出值之间的简单映射,也可能发生异常。
如果你不喜欢这些方法中的任何一种,至少考虑使用自己的异常(取决于原始异常)。