当前位置:  开发笔记 > 编程语言 > 正文

即使发生异常,如何最好地执行一组方法

如何解决《即使发生异常,如何最好地执行一组方法》经验,为你挑选了2个好方法。

在当前的Java项目中,我们有类似于以下示例的代码:

try {
    doSomeThing(anObject);
}
catch (SameException e) {
    // Do nothing or log, but don't abort current method.
}

try {
    doOtherThing(anObject);
}
catch (SameException e) {
    // Do nothing or log, but don't abort current method.
}

// ... some more calls to different method ...

try {
    finallyDoYetSomethingCompletelyDifferent(anObject);
}
catch (SameException e) {
    // Do nothing or log, but don't abort current method.
}

正如您所看到的,使用完全相同的对象调用了几个不同的方法,并且对于每个调用,捕获并处理相同的异常(或以非常类似的方式).异常不会被重新抛出,但可能只会被记录然后被丢弃.

try-catch围绕每个方法存在的唯一原因是始终执行所有方法,无论先前执行的方法是否失败.

我根本不喜欢上面的代码.它占用了大量的空间,非常重复(尤其是在catch-block中完成的日志记录;此处未提供)并且看起来很糟糕.

我可以想到其他一些编写代码的方法,但是也不太喜欢它们.我想到了以下选项:

循环切换顺序/用于案例范例

(参见维基百科或每日WTF)

for (int i = 0; i <= 9; i++) {
    try {
        switch (i) {
            case 0:
                doSomeThing(anObject); break;
            case 1:
                doOtherSomeThing(anObject); break;
            // ...More cases...
            case 9:
                doYetSomethingCompletelyDifferent(anObject); break;
        }
    }
    catch (SameException e) {
        // Do nothing or log, but don't abort current method.
    }
}

这显然是错误的代码,非常容易出错并且看起来很业余.

反射

使用反射来获取Method方法的对象,以便按照它们应该执行的顺序将它们存储在列表中.然后迭代此列表并使用anObjectas only参数调用该方法.异常在循环内部处理.

我不喜欢这种方法,因为错误(例如方法名称中的拼写错误)仅在运行时弹出,而Reflection API有些繁琐.

函子

像这样创建一个Functor类:

private class Functor
{
    void doStuff(MyObject object) throws SameException;
}

然后创建一个Functor调用方法的对象列表.像这样:

List functors = new ArrayList();

functors.add(new Functor() {
    @Override
    public void execute(MyObject anObject) {
        doSomeThing(anObject);
    }
});

functors.add(new Functor() {
    @Override
    public void execute(MyObject anObject) {
        doOtherSomeThing(anObject);
    }
});

稍后,迭代此列表并调用execute()每个Functor对象.我可以用两个词来总结我对这种方法的感觉:代码膨胀.


由于我不喜欢这四种方法,我想在这里讨论这个问题.你觉得最好的方法是什么?你是怎么解决过去的类似问题的?是否有一个我完全错过的更简单的解决方案?



1> PeterR..:

我会提倡重构方法(或" 我们为什么一开始就到这里来? "):

考虑为什么单个方法可以在使用myObject执行"stuff"之后抛出异常,然后可以安全地忽略该异常.由于异常会转义该方法,因此myObject必须处于未知状态.

如果忽略异常是安全的,那么肯定是错误的方式来传达每个方法中出错的地方.

相反,也许每个方法都需要对失败进行一些记录.如果不使用静态记录器,则可以将记录器传递给每个方法.



2> Jon Skeet..:

仿函数方法是我心目中最好的方法 - 遗憾的是,Java没有更好的方式来表示闭包或代理.这基本上就是你真正想要的,而在C#(和许多其他语言)中,这将是微不足道的.

你可以通过以下方式减少物理膨胀:

Functor[] functors = new Functor[] {
    new Functor() { @Override public void execute(MyObject anObject) {
        doSomeThing(anObject);
    }},
    new Functor() { @Override public void execute(MyObject anObject) {
        doSomeOtherThing(anObject);
    }}
};

在这里崩溃的空白可能会违背你正在使用的风格指南,但我认为它使代码更容易实际阅读,因为你可以更容易地看到肉.

最好开始游说Java 8中的闭包;)

推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有