有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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块的异常被禁止


共 (4) 个答案

  1. # 1 楼答案

    只处理try部分中的异常。除此之外的任何内容(包括finally部分)都不在try范围内,因此不处理异常

    如果要捕获/抑制finally块内的异常,需要用它自己的try/catch块包装if (br != null) br.close();,如下所示:

    ...
    } finally {
      try {
        if (br != null) br.close();
      } catch (Exception e) {
        // whatever handling
      }
    }
    ...
    

    此外,来自try块的异常被抑制,因为这是try块的行为——尝试一些东西并给您恢复的机会。由于在try块之后没有捕获任何异常,因此不会运行任何代码来响应它

    然后,无论是否引发任何异常,都会执行finally块。如果它抛出一个异常,并且因为它不在自己的try/catch块中,它的异常会传播到方法之外,并传播到调用方法

    以下面的评论为例,从Java 7开始,,您需要参考the documentation outlined here,并将重点放在题为“压制异常”的倒数第二节上,该节基本上说,可以从try块抛出多个异常,每个声明的资源最多抛出一个异常

    至于如果资源声明本身抛出异常会发生什么,我没有安装JDK7,所以我不确定。为什么不把下面的代码放在一个测试项目中(就像它看起来的那样,有一个虚假的路径),看看会发生什么,然后告诉我们结果是什么,这对每个人都有好处:

    try (BufferedReader br = new BufferedReader(new FileReader("a totally invalid path"))) {
      return br.readLine();
    }
    
  2. # 3 楼答案

    你想要什么样的行为?没有同时抛出多个异常的概念——因此其中一个异常必须“赢”。如果在语言中有一些一致的方式来表示“多个事情出了问题”(支持不仅仅是将一个异常包装到另一个异常中),那就太好了,但是船是在那个异常上航行的

    这就是番石榴有^{}的一个原因,这样原始的异常就不会被抑制

    编辑:请注意,在Java7中,资源试用功能有更多的选项。详见the documentation;它详细介绍了这一具体情况

  3. # 4 楼答案

    因为一个函数只能引发一个异常。后一个例外胜过所有前一个例外