Java 在循环体周围使用try/catch块抽象循环
让我们假设,我必须循环许多集合来检索数据。我想用try/catch块来封装每个迭代,以避免在出现错误时过早退出循环。例如:Java 在循环体周围使用try/catch块抽象循环,java,design-patterns,Java,Design Patterns,让我们假设,我必须循环许多集合来检索数据。我想用try/catch块来封装每个迭代,以避免在出现错误时过早退出循环。例如: for(Object o : aCollection) { try { // possible exception is thrown here } catch (Exception e) { // write log } } 然而,我的代码中有很多循环(for、enhance
for(Object o : aCollection) {
try {
// possible exception is thrown here
} catch (Exception e) {
// write log
}
}
然而,我的代码中有很多循环(for、enhanced for、while)。添加try/catch块容易出错,并且会降低代码的可读性
如何在不必编写大量样板代码的情况下向每个循环添加这样的块
是否有可以使用的模式/框架
您将如何解决此问题?我的评论建议使用策略模式的更详细版本:
public static <T> void forTryCatch(Iterable<T> it, Consumer<T> consumer) {
for (T t : it) {
try {
consumer.accept(t);
} catch (Exception e) {
// handle e
}
}
}
您可以抽象“for with try-catch”这件事,但我不推荐它,除非您的抽象做了一些更具体的事情来满足您的需求
你能做的是:
public class LoopUtils {
public static <T> void doLoop(Collection<T> coll, Processor<T> proc){
for(T t : coll){
try {
proc.process(t);
} catch (Exception ex) {
proc.handleException(ex);
}
}
}
}
public interface Processor<T> {
public void process(T t) throws Exception;
public void handleException(Exception ex);
}
公共类LoopUtils{
公共静态void doLoop(集合coll、处理器proc){
for(T:coll){
试一试{
过程(t);
}捕获(例外情况除外){
过程处理异常(ex);
}
}
}
}
公共接口处理器{
公共无效过程(T)抛出异常;
公共无效处理例外(例外情况除外);
}
用法:
Collection;
// ...
doLoop(一个集合,新处理器(){
公共作废进程(MyClass t)引发异常{
//做事。。。
}
公共无效句柄异常(异常除外){
//处理异常
}
});
为什么这不是一个好主意:它不会使代码更具可读性,也不会减少重复
当抽象(1)足够通用,可以在多个地方使用,同时(2)足够具体,可以实际实现底层语言或平台中尚未实现的东西时,抽象是有用的。如果不满足条件1,则根本没有抽象。若不满足条件2,那个么您就有一个例子:抽象并没有提供任何附加值,但它确实为bug的出现提供了不必要的限制和机会
此答案中的代码不符合条件2,因为它只是try-catch块的坏副本
但是,您应该研究有这么多循环的上下文。如果它们都对不同的集合执行类似的操作,或者它们都以相同的方式处理异常,那么某种抽象可能是合适的。为什么您的代码在正常操作期间首先抛出这么多异常?您可以使用策略模式。Java8Lambdas使这变得简单。(即,编写一个函数void
loopTryCatch(列表l,消费者c)
,并用loopTryCatch(myListOfInt,(int i)->System.out.println(i))调用它。
)请注意中的try/catch,而中的try/catch不能跳过会终止循环并导致无限循环的代码。@5gon12eder我们使用的是旧库,它不在我们的控制之下。添加try/catch块容易出错,使代码可读性降低。这两个语句都不是真的。try/catch本身不容易出错,try/catch语句可读性很强。非常感谢。这是一个很好的例子,但你是对的,它仍然太冗长了。谢谢阿德里安。无论如何,这是一个很好的例子。可以肯定的是,Java8会让它变得更简单
forTryCatch(Arrays.asList(1, 2, 3), new Consumer<Integer>() {
@Override
public void accept(Integer t) {
System.out.println(el);
}
});
forTryCatch(Arrays.asList(1, 2, 3), el -> {
System.out.println(el);
});
public class LoopUtils {
public static <T> void doLoop(Collection<T> coll, Processor<T> proc){
for(T t : coll){
try {
proc.process(t);
} catch (Exception ex) {
proc.handleException(ex);
}
}
}
}
public interface Processor<T> {
public void process(T t) throws Exception;
public void handleException(Exception ex);
}
Collection<MyClass> aCollection;
// ...
LoopUtils.doLoop(aCollection, new Processor<MyClass>() {
public void process(MyClass t) throws Exception {
// Do things...
}
public void handleException(Exception ex) {
// Handle the exception
}
});