为什么catch (Exception ex)
没有捕获Java中的某些异常?这是代码完全失败,出现未处理的异常。 (Java版本1.4)。
public static void main(String[] args) {
try {
//Code ...
} catch (Exception ex) {
System.err.println("Caught Exception");
ex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
}
finally {
app.shutdown();
}
System.exit(exitCode);
}
我得到Exception in thread "main" java.lang.NoSuchMethodError
但这有效
public static void main(String[] args) {
int exitCode = app.SUCCESS_EXIT_CODE;
try {
//Code ...
} catch (java.lang.NoSuchMethodError mex){
System.err.println("Caught NoSuchMethodError");
mex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
} catch (Exception ex) {
System.err.println("Caught Exception");
ex.printStackTrace();
exitCode = app.FAILURE_EXIT_CODE;
}
finally {
app.shutdown();
}
System.exit(exitCode);
}
我得到Caught NoSuchMethodError java.lang.NoSuchMethodError:
我认为捕获异常会捕获所有异常?如何捕获java中的所有异常?
答案 0 :(得分:116)
因为某些例外不是来自Exception
- 例如Throwable
和Error
。
基本上,类型层次结构是:
Object
|
Throwable
/ \
Exception Error
只能抛出Throwables
和派生类,所以如果你抓住Throwable
,那真的会抓住所有东西。
Throwable
,Exception
以及源自Exception
其他的任何异常,而不是RuntimeException
派生的已检查异常 - 他们是你必须宣布你会抛出的东西,或者如果你打电话给它们就会抓住它们。
总而言之,Java异常层次结构有点乱......
答案 1 :(得分:6)
类Exception及其子类 是一种Throwable表示的形式 条件是合理的 应用程序可能想要捕获。
- JavaDoc for java.lang.Exception
错误是Throwable的子类 这表明存在严重的问题 合理的申请不应该尝试 赶上。
您可能想要捕获某些错误,例如ThreadDeath。 ThreadDeath被归类为错误,如下所述
ThreadDeath类是专门的 Error的子类而不是 例外,即使它是“正常的 发生“,因为许多应用程序 捕获所有出现的异常和 然后丢弃例外。
但是,由于现在不推荐使用Thread的stop()方法,所以不应该使用它,因此你永远不应该看到ThreadDeath。
答案 2 :(得分:4)
异常只是一种Throwable; NoSuchMethodError不是Exception,而是Error,这是另一种Throwable。
答案 3 :(得分:3)
答案 4 :(得分:1)
正如其他海报所指出的,并非所有可投掷对象都是Exception
的子类。但是,在大多数情况下,捕获Error
或Throwable
并不是一个好主意,因为这些条件包括一些无法轻易恢复的严重错误情况。您的恢复代码可能会让事情变得更糟。
答案 5 :(得分:0)
正如其他帖子所指出的,catch(例外e)仅适用于源自Exception的异常。但是,如果查看树层次结构,您会注意到Throwable时出现异常。 Throwable也是Error的基类。因此,在NoSuchMethodError的情况下,它是一个错误而不是异常。请注意命名约定* Error vs. * Exception(例如,在IOException中)。
答案 6 :(得分:0)
首先让我们在这次讨论中澄清一些不幸的语义混淆。有java.lang.Exception
类,我们可以简单地将其称为具有大写'E'的异常。然后你有一个小写的'e'例外,它是一种语言特征。您可以在Throwable
类的documentation中查看小写版本:
出于编译时检查异常的目的,Throwable和 Throwable的任何子类,也不是它们的子类 RuntimeException或Error被视为已检查的异常。
对我而言,更容易将这个问题的答案视为已检查与未检查的异常(小写e)。必须在编译时考虑已检查的异常,而未经检查的异常则不在。异常(大写E)及其子类是经过检查的异常,这意味着您必须捕获代码可能抛出的任何异常,或声明方法可能抛出的异常(如果未捕获)。
错误,它的子类是未经检查的异常,这意味着您的代码既不必捕获可能引发的错误,也不必声明您抛出这些错误。 RunTimeException及其子类也是未经检查的异常,尽管它们位于类层次结构中。
请考虑以下代码:
void test() {
int a = 1, b = 0, c = a / b;
}
运行时,上面的代码将生成java.lang.ArithmeticException
。这将编译没有任何错误,即使抛出异常并且代码既没有捕获ArithmeticException也没有声明它抛出此异常。这是未经检查的例外的本质。
考虑ArithmeticException
在类层次结构中的位置,尤其是这是java.lang.Exception的子类。这里有一个异常,它派生自java.lang.Exception,但因为它也是java.lang.RuntimeException的子类,所以它是一个未经检查的异常,所以你不必捕获它。
java.lang.Object
java.lang.Throwable
java.lang.Exception
java.lang.RuntimeException
java.lang.ArithmeticException
如果你想捕捉任何可能被抛出的东西,赶上一个Throwable。然而,这可能不是最安全的事情,因为其中一些Throwable可能是致命的运行时条件,可能不应该被捕获。或者如果你抓住Throwable,你可能想要重新抛出你无法处理的Throwables。这取决于具体情况。