让我们假设,我必须循环许多集合来检索数据。我想用try / catch块封闭每次迭代,以避免在出现错误时过早退出循环。例如:
for(Object o : aCollection) {
try {
// possible exception is thrown here
} catch (Exception e) {
// write log
}
}
但是,我的代码中有很多循环(for,for,while)。添加try / catch块容易出错,并且使代码的可读性降低。
如何在不需要编写大量样板代码的情况下为每个循环添加这样的块?
是否有可以使用的模式/框架?
你会如何解决这个问题?
答案 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块的错误副本。
然而,你应该研究你有这么多循环的上下文。如果它们都使用不同的集合执行类似的操作,或者它们都以相同的方式处理异常,那么某种抽象可能是合适的。