首页 > 解决方案 > 如果我在 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

标签: java

解决方案


解释为什么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意味着您不必担心在Errors 的情况下发生泄漏,在您不想时恢复,或者捕获比您想要的更多的异常。

现在您可以尝试在不使用 的情况下解决上述三个问题finally,但它会引入其他问题。(例如,您可以在处理程序中Exception使用 a捕获然后重新抛出db.close(),但是您通常需要将封闭方法声明为throws Exception!)


请注意,这样的调用printStackTrace()是不可取的。更好的方法是使用日志框架……这样可以通过配置文件管理错误报告。


推荐阅读