问题
假设我有一个类和一个方法
class A {
void foo() throws Exception() {
...
}
}
现在我想为一个流如下所示的每个实例调用foo:A
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
问题:如何正确处理异常?代码无法在我的机器上编译,因为我没有处理foo()可能抛出的异常。 throws Exception
of bar
似乎在这里毫无用处。这是为什么?
#1 热门回答(96 赞)
你需要将方法调用包装到另一个方法调用中,而不会抛出检查异常。你仍然可以抛出RuntimeException
的子类。
一个普通的包装成语是这样的:
private void safeFoo(final A a) {
try {
a.foo();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
(超类型例外Exception
被用作例子,从不试图自己抓住它)
然后你可以用:as.forEach(this::safeFoo)
来调用它。
#2 热门回答(21 赞)
如果你想要的只是调用foo
,并且你更喜欢按原样传播异常(不包装),你也可以使用Java的for
loop(在将Stream转换为带有sometrickery的Iterable之后):
for (A a : (Iterable<A>) as::iterator) {
a.foo();
}
至少,这是我在JUnit测试中所做的,在那里我不想经历包装我的已检查异常的麻烦(实际上更喜欢我的测试来抛出未包装的原始异常)
#3 热门回答(13 赞)
这个问题可能有点旧,但因为我认为这里的"正确"答案只是一种可能导致某些问题隐藏在代码后面的问题。即使有一点Controversy,也存在Checked Exceptions。
你认为最优雅的方式是Misha这里给出的368585757只是在"期货"中执行动作。因此,你可以运行所有工作部件并收集不工作的例外作为单个部件。否则,你可以在列表中收集它们并稍后处理它们。
类似的方法来自Benji Weber。他建议创建一个自己的类型来收集工作而不是工作部分。
根据你真正想要实现的目标,输入值和输出值之间的简单映射可能也会对你有所帮助。
如果你不喜欢这些方式中的任何一种,请考虑使用(取决于原始异常)至少一个自己的异常。