在下面的代码中,我在finally块中关闭数据库,在finally块中关闭第二个数据库。有什么关系?那么final的用例是什么?因为控制权也会在catch块之后到达,所以我们可以释放资源。
try{
// initialise a database
} catch (Exception e) {
e.printStackTrace();
} finally{
db.close
}
第二
try{
// initialise a database
} catch (Exception e) {
e.printStackTrace();
}
db.close
答案 0 :(得分:2)
解释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
情况下的泄漏,不需要时恢复或捕获比您想要的更多的异常
现在,您可以尝试不使用finally
来解决上述三个问题,但这会带来其他问题。 (例如,您可以在处理程序中捕获Exception
然后将其db.close()
扔回throws Exception
,但是通常需要将封闭方法声明为printStackTrace()
!)
最后一个问题。建议不要这样调用adb shell input keyevent KEYCODE_MENU
。更好的方法是使用日志记录框架...,以便可以通过配置文件管理错误报告。
答案 1 :(得分:1)
Finally
,该块是safe point
来关闭资源,因为finally block
将在every situation
中执行,直到调用System#exit
为止。捕获也可能是thrown an exception
,在这种情况下,如果在捕获块之后放到外面,资源将不会关闭。
答案 2 :(得分:1)
在我看来,问题是在finally块中与在finally块之后关闭数据库连接之间有什么区别。
我将假定在try块内已打开数据库。如果try块中的代码引发了异常,并且仅在finally块之后关闭了数据库,则处理该异常时您将不会关闭数据库。
执行此操作的正确方法是在finally块中关闭数据库。无论是否引发异常,finally块都将无条件运行。
答案 3 :(得分:0)
考虑一些更具体的示例:
try{
// initialise a database
} catch (SocketException e) {
e.printStackTrace();
} finally{
db.close
}
即使异常不是 SocketException,这也将清除。
try{
// initialise a database
} catch (SocketException e) {
e.printStackTrace();
}
db.close
不会。只会冒出异常。
(我随机选择SocketException。当然,其他Exception,Throwables等也是如此)
基线:使用finally块执行清理可增强代码免受意外异常和在catch块中引发的异常的影响。