Java7 多个异常处理

Java7 multiple exception handling

我一直在寻找这个问题的答案,但没有得到满意的解释。这是一些背景:

Java 7 允许我们在单个 catch 块中捕获多个异常,前提是这些异常来自不同的层次结构。例如:

try {
    // some code

} catch(SQLException | FileNotFoundException e) {
    e.printStackTrace();
} catch(Exception e) {
    e.printStackTrace();
}

但是如果异常来自同一层次结构,我们必须使用多个 catch 块,例如:

try {
    // some code
} catch(FileNotFoundException  e) {
    e.printStackTrace();
} catch(IOException e) {
    e.printStackTrace();
}

但是如果我尝试编写如下代码,编译器会抱怨 "The exception FileNotFoundException is already caught by the alternative IOException"

try {
    // some code
} catch(FileNotFoundException | IOException  e) { // compiler error
    e.printStackTrace();
}

现在我的问题是:为什么编译器在最后一种情况下报错,它不能弄清楚FileNotFoundExceptionIOException的特例吗?当我的异常处理逻辑相同时,这将节省代码重复。

Why compiler reports an error in last case, can't it figure out that FileNotFoundException is special case of IOException?

因为FileNotFoundExceptionIOException的子类。换句话说,“FileNotFoundException |”部分是多余的。

以下代码没问题的原因...

} catch(FileNotFoundException  e) {
    ...
} catch(IOException e) {
    ...
}

...是因为这里 IOException 子句很重要:例如,如果抛出 SocketException,它将通过 FileNotFoundException 部分,并陷入IOException 子句。

捕获异常时,您已将捕获子句从最具体到最一般排序。

考虑以下层次结构:

class MyException extends Exception {}

class MySubException extends MyException  {}

如果您的代码的一部分抛出 MyException 而另一部分抛出 MySubException,您必须先捕获 MySubException。

catch(MySubException e){

} catch(MyException e){

}

这和使用 instanceof 运算符是一样的。

如果您测试 MySubException 的实例是否是 MyException 的实例,结果将为真。

mse = new MySubException();

if(mse instanceof MyException){
    println("MyException");
} else if(mse instanceof MySubException){
    println("MySubException");
}

这段代码永远不会打印 "MySubException"。

mse = new MySubException();

if(mse instanceof MySubException){
    println("MySubException");
} else if(mse instanceof MyException){
    println("MyException");
}

这是正确的顺序。

这是因为 FileNotFoundException 扩展了 IOException,正如你所说的,它具有相同的层次结构,你不能将它们添加到同一个 catch 块中。