我一直试图找到这个问题的答案,但没有得到任何令人满意的解释。以下是一些背景知识:
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();
}
但是,如果我尝试编写如下代码,编译器会抱怨“异常FileNotFoundException
已被替代IOException
抓住”
try {
// some code
} catch(FileNotFoundException | IOException e) { // compiler error
e.printStackTrace();
}
现在我的问题是:为什么编译器在最后一种情况下报告错误,不能指出FileNotFoundException
是IOException
的特例?当我的异常处理逻辑相同时,这将节省代码重复。
答案 0 :(得分:13)
为什么编译器在最后一种情况下报告错误,是否会发现
// Alternative to Vector: List<String> list = new ArrayList<>(); list.add("alpha"); for (String s : list) { ... } // Alternative to Enumeration: Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String s = iterator.next(); }
是FileNotFoundException
的特例?
因为IOException
是FileNotFoundException
的子类。换句话说,&#34; IOException
&#34;部分是多余的。
以下代码的原因是正确的......
FileNotFoundException |
...因为这里} catch(FileNotFoundException e) {
...
} catch(IOException e) {
...
}
子句很重要:例如,如果抛出IOException
,它将通过SocketException
部分传递,并被FileNotFoundException
抓住1}}子句。
答案 1 :(得分:0)
在捕获异常时,您已经从最具体到最常规的顺序订购了catch子句。
考虑以下层次结构:
class MyException extends Exception {}
class MySubException extends MyException {}
如果代码的一部分抛出MyException而另一部分抛出MySubException,则必须首先捕获MySubException。
catch(MySubException e){
} catch(MyException e){
}
与使用instanceof运算符相同。
如果您测试MySubException的实例是否是MyException的实例,结果将为true。
mse = new MySubException();
if(mse instanceof MyException){
println("MyException");
} else if(mse instanceof MySubException){
println("MySubException");
}
这段代码永远不会打印&#34; MySubException&#34;。
mse = new MySubException();
if(mse instanceof MySubException){
println("MySubException");
} else if(mse instanceof MyException){
println("MyException");
}
这将是正确的顺序。
答案 2 :(得分:0)
因为FileNotFoundException扩展了IOException,正如你所说的相同层次结构,你不能将它们添加到同一个catch块。