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();
}
现在我的问题是:为什么编译器在最后一种情况下报错,它不能弄清楚FileNotFoundException
是IOException
的特例吗?当我的异常处理逻辑相同时,这将节省代码重复。
Why compiler reports an error in last case, can't it figure out that FileNotFoundException
is special case of IOException
?
因为FileNotFoundException
是IOException
的子类。换句话说,“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 块中。
我一直在寻找这个问题的答案,但没有得到满意的解释。这是一些背景:
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();
}
现在我的问题是:为什么编译器在最后一种情况下报错,它不能弄清楚FileNotFoundException
是IOException
的特例吗?当我的异常处理逻辑相同时,这将节省代码重复。
Why compiler reports an error in last case, can't it figure out that
FileNotFoundException
is special case ofIOException
?
因为FileNotFoundException
是IOException
的子类。换句话说,“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 块中。