Bas*_*ian 154 java unhandled-exception java-8 java-stream
假设我有一个类和一个方法
class A {
void foo() throws Exception() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
现在我想为A一个流传递的每个实例调用foo,如:
void bar() throws Exception {
Stream<A> as = ...
as.forEach(a -> a.foo());
}
Run Code Online (Sandbox Code Playgroud)
问题:如何正确处理异常?代码无法在我的机器上编译,因为我没有处理foo()可能抛出的异常.在throws Exception的bar似乎是没用在这里.这是为什么?
ski*_*iwi 134
您需要将方法调用包装到另一个方法中,在此方法中不会抛出已检查的异常.你仍然可以抛出任何子类RuntimeException.
一个普通的包装习语是这样的:
private void safeFoo(final A a) {
try {
a.foo();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
(超类型的例外Exception是仅作为例子,切勿尝试自行抓住它)
然后你可以用:as.forEach(this::safeFoo).
ava*_*sen 27
如果您只想调用foo,并且您希望按原样传播异常(不包装),那么您也可以使用Java for循环(在将Stream转换为具有一些技巧的Iterable之后):
for (A a : (Iterable<A>) as::iterator) {
a.foo();
}
Run Code Online (Sandbox Code Playgroud)
至少,这是我在JUnit测试中所做的,我不想经历包装我检查的异常的麻烦(实际上更喜欢我的测试抛弃未包装的原始异常)
Mar*_*ano 13
这个问题可能有点老了,但因为我认为"正确"的答案在这里只有一条路可导致隐藏的问题后面的代码中的一些问题.即使存在一些争议,也存在Checked Exceptions.
在我看来,最优雅的方式可你发现在这里给出的米沙 在Java中8流聚集运行时异常 由刚刚在"期货"执行的操作.因此,您可以运行所有工作部件,并将单独的异常工作收集起来.否则,您可以在列表中收集它们并稍后处理它们.
类似的方法来自Benji Weber.他建议创建一个自己的类型来收集工作而不是工作部分.
根据您真正想要实现的目标,输入值和输出值之间的简单映射可能也会对您有所帮助.
如果您不喜欢这些方法中的任何一种,请考虑使用(取决于原始异常)至少一个自己的异常.
fbo*_*kov 10
我建议使用Google Guava Throwables类
传播( Throwable throwable)
如果它是RuntimeException或Error的实例,则传播throwable as as,否则作为最后的手段,将其包装在RuntimeException中然后传播.**
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
throw Throwables.propagate(e);
}
});
}
Run Code Online (Sandbox Code Playgroud)
更新:
现在不推荐使用:
void bar() {
Stream<A> as = ...
as.forEach(a -> {
try {
a.foo()
} catch(Exception e) {
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
});
}
Run Code Online (Sandbox Code Playgroud)
您可以通过这种方式包装和解包异常.
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);
}
}
Run Code Online (Sandbox Code Playgroud)
您可能希望执行以下操作之一:
有几个库可以让您轻松完成.下面的示例是使用我的NoException库编写的.
// Propagate checked exception
as.forEach(Exceptions.sneak().consumer(A::foo));
// Wrap and propagate unchecked exception
as.forEach(Exceptions.wrap().consumer(A::foo));
as.forEach(Exceptions.wrap(MyUncheckedException::new).consumer(A::foo));
// Catch the exception and stop propagation (using logging handler for example)
as.forEach(Exceptions.log().consumer(Exceptions.sneak().consumer(A::foo)));
Run Code Online (Sandbox Code Playgroud)
更易读的方式:
class A {
void foo() throws MyException() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
只需将其隐藏在 a 中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();
}
}
Run Code Online (Sandbox Code Playgroud)
尽管在这一点上,如果有人说跳过流并使用 for 循环,我不会反对他们,除非:
Collection.stream(),即不是直接转换为 for 循环。parallelstream()| 归档时间: |
|
| 查看次数: |
135519 次 |
| 最近记录: |