在循环体周围用try / catch块抽象循环

时间:2015-02-20 20:33:47

标签: java design-patterns

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

for(Object o : aCollection) {
   try {
         // possible exception is thrown here
       } catch (Exception e) {
          // write log             
     }
 }

但是,我的代码中有很多循环(for,for,while)。添加try / catch块容易出错,并且使代码的可读性降低。

如何在不需要编写大量样板代码的情况下为每个循环添加这样的块?

是否有可以使用的模式/框架?

你会如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

我的评论的更详细版本建议使用策略模式:

public static <T> void forTryCatch(Iterable<T> it, Consumer<T> consumer) {
    for (T t : it) {
        try {
            consumer.accept(t);
        } catch (Exception e) {
            // handle e
        }
    }
}

如果您没有Java8,那么您需要定义消费者:

public interface Consumer<T> {
    void accept(T t);
}

并像这样使用它:

forTryCatch(Arrays.asList(1, 2, 3), new Consumer<Integer>() {
    @Override
    public void accept(Integer t) {
        System.out.println(el);
    }
});

不幸的是,这非常冗长,所以除非你在forTryCatch中有很多其他代码,否则它可能不值得。

在Java8中,Consumer已经存在,并且使用该函数要短得多:

forTryCatch(Arrays.asList(1, 2, 3), el -> {
    System.out.println(el);
});

答案 1 :(得分:0)

你可以抽象出“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);

}

使用方法:

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

为什么这不是一个好主意:它不会使代码更具可读性,也不会减少重复。

抽象是有用的,因为它们(1)足够通用,可以在多个地方使用,而同时(2)具体到足以使它们实际实现尚未在底层语言中实现的内容或平台。如果不满足条件1,则根本没有抽象。如果不满足条件2那么你有一个Inner-platform effect的例子:抽象没有提供任何附加价值,而它确实提供了不必要的限制和出现错误的机会。

此答案中的代码不符合条件2,因为它只是try-catch块的错误副本。

然而,你应该研究你有这么多循环的上下文。如果它们都使用不同的集合执行类似的操作,或者它们都以相同的方式处理异常,那么某种抽象可能是合适的。