假设我有一个类和一个方法
class A {
void foo() throws Exception() {
...
}
}
现在,我想为通过如下流传递的每个A
实例调用foo:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
问:如何正确处理异常?代码不能在我的机器上编译,因为我不处理foo()可能抛出的异常。bar
的throws Exception
在这里似乎没有用。为什么会这样呢?
发布于 2015-09-19 21:30:36
如果您想要的只是调用foo
,并且您更喜欢按原样传播异常(没有包装),那么您也可以使用Java的for
循环来代替(在将流转换为带有一些trickery的Iterable之后):
for (A a : (Iterable<A>) as::iterator) {
a.foo();
}
这至少是我在JUnit测试中所做的,我不想经历包装我的受检异常的麻烦(实际上,我更喜欢我的测试抛出未包装的原始异常)。
发布于 2015-10-19 23:51:18
这个问题可能有点老了,但因为我认为这里的“正确”答案只有一种,这可能会导致一些问题,隐藏在你的代码中。即使有一点Controversy,检查异常的存在也是有原因的。
在我看来,你能找到的最优雅的方式是Misha here Aggregate runtime exceptions in Java 8 streams通过执行“未来”中的动作。因此,您可以运行所有工作部分,并将不工作的异常收集为单个异常。否则,您可以将它们全部收集到一个列表中,并在以后处理它们。
Benji Weber也采用了类似的方法。他建议创建一个自己的类型来收集工作部件和非工作部件。
根据您真正想要实现的输入值和输出值之间的简单映射,发生的异常可能也适用于您。
如果您不喜欢这些方法中的任何一种,请考虑使用(取决于原始异常)至少一个自己的异常。
发布于 2014-05-13 23:48:25
你可以用这种方式包装和解包异常。
class A {
void foo() throws Exception {
throw new Exception();
}
};
interface Task {
void run() throws Exception;
}
static class TaskException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TaskException(Exception e) {
super(e);
}
}
void bar() throws Exception {
Stream<A> as = Stream.generate(()->new A());
try {
as.forEach(a -> wrapException(() -> a.foo())); // or a::foo instead of () -> a.foo()
} catch (TaskException e) {
throw (Exception)e.getCause();
}
}
static void wrapException(Task task) {
try {
task.run();
} catch (Exception e) {
throw new TaskException(e);
}
}
https://stackoverflow.com/questions/23548589
复制相似问题