我有一个关于异常处理和资源管理的问题,我想知道是否有人可以分享他们的意见。我需要执行一系列操作:读取应用程序设置,设置环境,执行内容然后最终清理。清理涉及拆除环境,但只有在首先成功设置时才会发生这种情况。
这是我的第一个(也是蹩脚的)方法:
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;
。
答案 0 :(得分:2)
如果两种方式完成您打算做的事情,正确或错误都不会。
在我看来,第二种方法(big try / catch / finally块)更容易阅读,因为你的方法体中某处的catch块中没有“隐藏”的返回语句。
此外,我认为删除方法之间的相互依赖关系(拆解,设置)通常是一种很好的做法(例如,您可以单独对这些方法进行单元测试)。如果没有设置任何东西就退出拆机 - 不需要为此感到奇怪:)
答案 1 :(得分:2)
finally
方法用于具有保证,在抛出异常之前,可以关闭/取消引用所使用的资源(并准备好进行垃圾回收)。这只是为了宣传exception safety。
您刚才在此讨论的内容称为Dispose Pattern。基本上,由于Java GC的自动特性,您正在为运行时环境进行资源清理。
您的第二种方法是正确的(这是一种Dispose模式),因为您使用tearDownEnvironment()
有效地清理环境,在JVM GC启动之前关闭所有资源。
额外信息:Resource Acquisition Is Initialization 可以启发你吗?
答案 2 :(得分:1)
通常,您的teardownEnvironment()
会检查
isEnvironmentSetCorrectly()
或if(environment != null)
或类似的任何
在你开始拆除之前。
所以你不必“感觉有点奇怪”,因为如果做得不好就不会发生。