Java 在循环体周围使用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

让我们假设,我必须循环许多集合来检索数据。我想用try/catch块来封装每个迭代,以避免在出现错误时过早退出循环。例如:

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
    }
});