在 Java 中捕获异常的顺序
如果我没有记错的话,应该首先捕获异常的子类。但是必须捕获任何运行时异常和一个具体的检查异常,首先应该捕获哪些异常?
try {
...
} catch(RuntimeException e) {
...
} catch(IOException e) {
...
}
这个顺序是否正确?还是它是正确的,但一个糟糕的选择?
如果我没有记错的话,应该首先捕获异常的子类。但是必须捕获任何运行时异常和一个具体的检查异常,首先应该捕获哪些异常?
try {
...
} catch(RuntimeException e) {
...
} catch(IOException e) {
...
}
这个顺序是否正确?还是它是正确的,但一个糟糕的选择?
顺序是首先匹配的,被执行(正如JLS清楚地解释的那样)。
如果第一个 catch 与异常匹配,它将执行,如果没有,则尝试下一个 catch 并打开,直到一个匹配或没有匹配。
因此,在捕获异常时,您希望始终首先捕获最具体的异常,然后捕获最通用的异常(如 RuntimeException 或 Exception)。例如,假设你想捕获 String.charAt(index) 方法抛出的 StringIndexOutOfBoundsException,但你的代码也可能引发 NullPointerException,下面介绍了如何捕获异常:
String s = null;
try {
s.charAt(10);
} catch ( NullPointerExeption e ) {
System.out.println("null");
e.printStackTrace();
} catch ( StringIndexOutOfBoundsException e ) {
System.out.println("String index error!");
e.printStackTrace();
} catch ( RuntimeException e ) {
System.out.println("runtime exception!");
e.printStackTrace();
}
因此,通过此顺序,我确保正确捕获异常并且它们不会相互绊倒,如果它是NullPointerException,则进入第一个捕获,如果StringIndexOutOfBoundsException,则进入第二个,最后,如果它是运行时异常(或从它继承,如非法参数异常),则进入第三个捕获。
您的情况是正确的,因为 IOException 继承自 Exception,而 RuntimeException 也继承自 Exception,因此它们不会相互绊倒。
首先捕获一般异常,然后再捕获它的后代之一也是一个编译错误,如下所示:
try {
// some code here
} catch ( Exception e) {
e.printStackTrace();
} catch ( RuntimeException e ) { // this line will cause a compilation error because it would never be executed since the first catch would pick the exception
e.printStackTrace();
}
因此,您应该首先拥有子项,然后是父项例外。
这个顺序是否正确?还是它是正确的,但一个糟糕的选择?
也不。正如其他答案所说,编译器应该告诉你,如果你把简单的捕获放在一个掩蔽另一个的顺序中。
但是你的代码中还有另一个潜在的问题:你是否真的在捕捉。问题在于,uuncheck异常的来源/原因有很多,其中许多来源/原因实际上是应用程序中的错误。RuntimeException
在紧急关机过程中使用 记录诊断程序是可以的,但是如果您发现并尝试从 中恢复,则需要小心,以免在地毯下清除严重问题:catch
RuntimeException
无论如何,请确保记录异常及其堆栈跟踪。
考虑尝试恢复是否明智。如果您有一个未知的错误,它可能会在触发异常之前造成不可预测的损害。您无法知道应用程序是否可以恢复,或者它是否可能通过尝试继续而造成更严重的损害。
同样的建议也适用于捕捉和 / .而且由于可能已经发生的损害的性质,它更为关键。Exception
Throwable
Error
Throwable
Error