在 catch 块内抛出的异常 - 它会再次被捕获吗?

2022-08-31 05:48:50

这似乎是一个编程101问题,我原以为我知道答案,但现在发现自己需要仔细检查。在下面的这段代码中,在第一个 catch 块中引发的异常是否会被下面的常规 Exception catch 块捕获?

try {
  // Do something
} catch(IOException e) {
  throw new ApplicationException("Problem connecting to server");
} catch(Exception e) {
  // Will the ApplicationException be caught here?
}

我一直以为答案是否定的,但现在我有一些奇怪的行为可能是由此引起的。对于大多数语言来说,答案可能是一样的,但我使用的是Java。


答案 1

不,因为新的不直接在块中。throwtry


答案 2

不。检查起来非常简单。

public class Catch {
    public static void main(String[] args) {
        try {
            throw new java.io.IOException();
        } catch (java.io.IOException exc) {
            System.err.println("In catch IOException: "+exc.getClass());
            throw new RuntimeException();
        } catch (Exception exc) {
            System.err.println("In catch Exception: "+exc.getClass());
        } finally {
            System.err.println("In finally");
        }
    }
}

应打印:

In catch IOException: class java.io.IOException
In finally
Exception in thread "main" java.lang.RuntimeException
        at Catch.main(Catch.java:8)

从技术上讲,这可能是编译器错误,实现依赖,未指定的行为或其他原因。但是,JLS已经很好地确定了,编译器对于这种简单的事情来说已经足够好了(泛型的角落情况可能是另一回事)。

另请注意,如果交换两个 catch 块,它将不会编译。第二个渔获将完全无法实现。

请注意,即使执行了 catch 块,finally 块也始终会运行(除了愚蠢的情况,例如无限循环、通过工具接口附加并终止线程、重写字节码等)。