java - 如果我在 try/catch 之后关闭数据库连接而不是 finally
问题描述
在以下两个示例中,我是 1)在finally
块中关闭数据库,2)在try
...之后关闭它catch
。使用哪种方法有区别吗?如果不是,那有什么意义finally
,因为我们可以在不使用资源的情况下释放资源?
try{
// initialise a database connection
} catch (Exception e) {
e.printStackTrace();
} finally{
db.close
}
第二
try{
// initialise a database connection
} catch (Exception e) {
e.printStackTrace();
}
db.close
解决方案
解释为什么finally
更好/必要的一种方法是指出此版本代码中的缺陷:
try {
// initialise a database
} catch (Exception e) {
e.printStackTrace();
}
db.close();
第一个问题是,如果抛出某个子类型的Error
异常,则try ... catch
不会捕获它。 Error
是 的子类型,Throwable
但不是Exception
。
您可能会反驳说,不应尝试从Error
异常中恢复。在许多情况下都是如此,但在其他情况下则不然。例如,如果这段代码是在工作线程中执行的,很多框架会尝试创建一个新线程来替换死掉的线程。这将导致数据库句柄泄漏。
第二个问题是您正在捕获和挤压异常。实际上,对于您编写的代码,您必须这样做才能db.close()
在最后执行。这可能适用于您的示例,但一般不会起作用。例如,如果您需要从此代码中返回某些内容……或者允许传播异常以供调用者处理,该怎么办。
第三个问题是你正在捕捉Exception
,以便db.close()
在所有情况下都可以关闭。但是,通过这样做,您很可能会捕获不应在此级别捕获的异常。例如,如果带有 try 块的东西抛出 NPE,你不应该“挤压和恢复”。相反,您应该允许异常传播。
请注意,使用finally
意味着您不必担心在Error
s 的情况下发生泄漏,在您不想时恢复,或者捕获比您想要的更多的异常。
现在您可以尝试在不使用 的情况下解决上述三个问题finally
,但它会引入其他问题。(例如,您可以在处理程序中Exception
使用 a捕获然后重新抛出db.close()
,但是您通常需要将封闭方法声明为throws Exception
!)
请注意,这样的调用printStackTrace()
是不可取的。更好的方法是使用日志框架……这样可以通过配置文件管理错误报告。
推荐阅读
- c++ - 如何将 torch::tensor 形状与其他一些形状进行比较?
- performance - 有没有利用按字母顺序排列的倒排索引的算法?
- reactjs - 反应按钮单击事件无法正常工作
- r - 使用 Caret 和食谱训练模型:错误并非食谱中的所有变量都存在
- rust - 如何在 Rust HashMap 中使用引用计数键?
- java - 图像/外部 css 未在 Freemarker 模板中加载
- javascript - 对象中的匿名箭头函数
- kubernetes - 服务未与 Rollout 连接
- django - 有没有办法可以在 Django 旁边运行 Discord 机器人?
- rust - vanilla Rust 中的目录遍历