trycatchfinally block在try和finally block都抛出异常时的java行为?
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
如果readLine和close方法都抛出异常,那么readFirstLineFromFileWithFinallyBlock方法抛出finally块抛出的异常;从try块抛出的异常被抑制。为什么会有这样的行为?为什么try块的异常被禁止
# 1 楼答案
只处理
try
部分中的异常。除此之外的任何内容(包括finally
部分)都不在try
范围内,因此不处理异常如果要捕获/抑制
finally
块内的异常,需要用它自己的try/catch块包装if (br != null) br.close();
,如下所示:此外,来自
try
块的异常被抑制,因为这是try
块的行为——尝试一些东西并给您恢复的机会。由于在try
块之后没有捕获任何异常,因此不会运行任何代码来响应它然后,无论是否引发任何异常,都会执行
finally
块。如果它抛出一个异常,并且因为它不在自己的try/catch块中,它的异常会传播到方法之外,并传播到调用方法以下面的评论为例,从Java 7开始,,您需要参考the documentation outlined here,并将重点放在题为“压制异常”的倒数第二节上,该节基本上说,可以从
try
块抛出多个异常,每个声明的资源最多抛出一个异常至于如果资源声明本身抛出异常会发生什么,我没有安装JDK7,所以我不确定。为什么不把下面的代码放在一个测试项目中(就像它看起来的那样,有一个虚假的路径),看看会发生什么,然后告诉我们结果是什么,这对每个人都有好处:
# 2 楼答案
它只能抛出一个异常,根据规范,“最终”块中的异常将获胜
最后,出于这个原因,块的编码应该总是非常防御性的。见:
Is a finally block without a catch block a java anti-pattern?
# 3 楼答案
你想要什么样的行为?没有同时抛出多个异常的概念——因此其中一个异常必须“赢”。如果在语言中有一些一致的方式来表示“多个事情出了问题”(支持不仅仅是将一个异常包装到另一个异常中),那就太好了,但是船是在那个异常上航行的
这就是番石榴有^{} 的一个原因,这样原始的异常就不会被抑制
编辑:请注意,在Java7中,资源试用功能有更多的选项。详见the documentation;它详细介绍了这一具体情况
# 4 楼答案
因为一个函数只能引发一个异常。后一个例外胜过所有前一个例外