你弄脏之前先清理干净吗?将清理代码放入finally块中

时间:2010-11-26 11:28:35

标签: java exception-handling resource-management

我有一个关于异常处理和资源管理的问题,我想知道是否有人可以分享他们的意见。我需要执行一系列操作:读取应用程序设置,设置环境,执行内容然后最终清理。清理涉及拆除环境,但只有在首先成功设置时才会发生这种情况。

这是我的第一个(也是蹩脚的)方法:

try {
 readSettings();
 setupEnvironment();
} catch (Exception ex) {
 logStackTrace(ex);
 displayError(ex);
 closeCommThreads();
 return;
}

try {
 // do stuff
} catch (Exception ex) {
 logStackTrace(ex);
 displayError(ex);
} finally {
 teardownEnvironment();
 closeCommThreads();
}

这看起来有点难看,所以我决定寻找更好的解决方案。我做了一些背景阅读,很多文章投票支持更大的try/catch块并使用(双关语?)finally进行清理。所以这是我的第二次尝试:

try {
 readSettings();
 setupEnvironment();
 // do stuff
} catch (Exception ex) {
 logStackTrace(ex);
 displayError(ex);
} finally {
 teardownEnvironment();
 closeCommThreads();
}

为了完成这项工作,我不得不从teardownEnvironment()删除顺序耦合,以便可以在setupEnvironment()之前或之后随时调用它(对于编辑:任何更好的方法?)。这是正确的方法吗?在安装之前我确实感到有点奇怪。

编辑:

只是为了使它更明确一点:我通过在teardownEnvironment中添加额外的检查来删除顺序耦合 - 类似于if (!isSetup()) return;

3 个答案:

答案 0 :(得分:2)

如果两种方式完成您打算做的事情,正确错误都不会。

在我看来,第二种方法(big try / catch / finally块)更容易阅读,因为你的方法体中某处的catch块中没有“隐藏”的返回语句。

此外,我认为删除方法之间的相互依赖关系(拆解,设置)通常是一种很好的做法(例如,您可以单独对这些方法进行单元测试)。如果没有设置任何东西就退出拆机 - 不需要为此感到奇怪:)

答案 1 :(得分:2)

finally方法用于具有保证,在抛出异常之前,可以关闭/取消引用所使用的资源(并准备好进行垃圾回收)。这只是为了宣传exception safety

您刚才在此讨论的内容称为Dispose Pattern。基本上,由于Java GC的自动特性,您正在为运行时环境进行资源清理。

您的第二种方法是正确的(这是一种Dispose模式),因为您使用tearDownEnvironment()有效地清理环境,在J​​VM GC启动之前关闭所有资源。

额外信息:Resource Acquisition Is Initialization 可以启发你吗?

答案 2 :(得分:1)

通常,您的teardownEnvironment()会检查

isEnvironmentSetCorrectly()if(environment != null)或类似的任何

在你开始拆除之前。

所以你不必“感觉有点奇怪”,因为如果做得不好就不会发生。