51

为什么Java中的一些异常没有被捕获catch (Exception ex)?这是代码完全失败并出现未处理的异常。(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中的所有异常?

4

7 回答 7

135

因为有些例外不是从Exception- 例如ThrowableError.

基本上类型层次结构是:

       Object
         |
      Throwable
     /         \
Exception      Error

只能Throwables抛出派生类,所以如果你 catch Throwable,那真的会抓住一切。

Throwable,Exception以及任何源自Exception 源自RuntimeExceptioncount 的异常之外的异常- 它们是您必须声明您将抛出的异常,或者如果您调用抛出它们的东西则捕获它们。

总而言之,Java 异常层次结构有点混乱......

于 2009-09-03T18:27:10.613 回答
6

Errors 不是Exceptions。

类 Exception 及其子类是 Throwable 的一种形式,它指示合理的应用程序可能想要捕获的条件。

-- java.lang.Exception 的 JavaDoc

Error 是 Throwable 的子类,表示合理的应用程序不应尝试捕获的严重问题。

-- java.lang.Error 的 JavaDoc

您可能想要捕获某些错误,例如ThreadDeath。ThreadDeath 被归类为错误,如下所述

ThreadDeath 类特别是 Error 而不是 Exception 的子类,即使它是“正常发生”,因为许多应用程序捕获所有发生的 Exception 然后丢弃异常。

-- ThreadDeath 的 JavaDoc

但是,由于现在不推荐使用 Thread 的 stop() 方法,因此您不应该使用它,因此您永远不会看到 ThreadDeath。

于 2009-09-03T18:37:01.807 回答
4

Exception 只是 Throwable 的一种;NoSuchMethodError 不是Exception,而是Error,是另一种Throwable。

于 2009-09-03T18:27:55.870 回答
3

你可以抓到Throwable。错误和异常扩展Throwable

请参阅 Throwable JavaDoc

Throwable 类是 Java 语言中所有错误和异常的超类。

于 2009-09-03T18:27:39.287 回答
1

正如其他海报所指出的那样,并非所有可投掷对象都是Exception. Error但是,在大多数情况下,捕获or并不是一个好主意Throwable,因为这些条件包括一些非常严重的错误条件,这些错误条件无法轻易恢复。您的恢复代码可能只会让事情变得更糟。

于 2009-09-03T18:31:32.710 回答
1

首先让我们澄清一下本次讨论中一些不幸的语义混淆。有一个java.lang.Exception类,我们可以简单地将其称为带有大写“E”的 Exception。然后你有一个小写“e”的例外,这是一种语言特性。您可以在该类的文档中查看小写版本Throwable

出于对异常的编译时检查的目的,Throwable 和任何不是 RuntimeException 或 Error 的子类的 Throwable 子类都被视为已检查异常。

对我来说,更容易将这个问题的答案视为已检查与未检查的异常(小写 e)。已检查的异常必须在编译时考虑,而未检查的异常则不需要。异常(大写 E)及其子类是已检查异常,这意味着您要么必须捕获代码可能抛出的任何异常,要么声明您的方法可能抛出的异常(如果未捕获)。

Error 及其子类是未经检查的异常,这意味着您的代码既不必捕获可能抛出的错误,也不必声明抛出这些错误。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,您可能想要重新抛出您无法处理的 Throwable。这取决于上下文。

于 2018-06-13T16:05:04.680 回答
0

正如其他两篇文章所指出的,catch(Exception e) 仅适用于派生自Exception的异常。但是,如果您查看树层次结构,您会注意到 Exception if Throwable。Throwable 也是Error的基类。因此,在 NoSuchMethodError 的情况下,它是错误而不是异常。请注意命名约定 *Error 与 *Exception(例如,在 IOException 中)。

于 2009-09-03T18:30:58.047 回答