【问题标题】:Java exception not caught未捕获 Java 异常
【发布时间】:2010-11-25 09:31:24
【问题描述】:

为什么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 中捕获所有异常?

【问题讨论】:

    标签: java exception try-catch


    【解决方案1】:

    因为某些异常并非源自 Exception - 例如ThrowableError

    基本上类型层次是:

           Object
             |
          Throwable
         /         \
    Exception      Error
    

    只有Throwables 和派生类可以被抛出,所以如果你抓住Throwable,那真的会抓住一切。

    ThrowableException 以及源自Exception 的任何异常其他而不是源自RuntimeException 的异常都算作已检查异常 - 他们就是那些你必须声明你会抛出,或者如果你调用抛出它们的东西,你就会抓住它们。

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

    【讨论】:

    • 错误并不是真正的异常,因此它们不是从异常派生的。
    • @R. Bemrose - 它们符合 Java 语言规范:“每个异常都由 Throwable 类或其子类之一的实例表示”和“未经检查的异常类是 RuntimeException 类及其子类,以及 Error 类及其子类。”
    • 我很确定 Throwable 在技术上是一个“检查异常”。我最近考试弄错了。
    • 这里也解释得很好(有类似的图表):geeksforgeeks.org/checked-vs-unchecked-exceptions-in-java
    【解决方案2】:

    Errors 不是 Exceptions。

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

    -- JavaDoc for java.lang.Exception

    错误是 Throwable 的子类 这表明严重的问题 合理的应用不应该尝试 赶上。

    -- JavaDoc for java.lang.Error

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

    ThreadDeath 类具体是 Error 的子类而不是 例外,即使它是“正常的 发生”,因为许多应用程序 捕获所有出现的异常和 然后丢弃异常。

    -- JavaDoc for ThreadDeath

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

    【讨论】:

    • Java 语言规范不同意你的观点:“未经检查的异常类是 RuntimeException 类及其子类,以及 Error 类及其子类。”
    • 我特别感谢关于不捕获错误的建议。考虑OutOfMemoryErrors - 一旦被抛出,应用程序可能会处于错误状态。捕获并丢弃这种Error 是不明智的。
    • 基本上,JLS 总是将“可以抛出和捕获的事物”称为异常。您在那里引用的任何内容都没有说明错误不是例外。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      你可以赶上Throwable。错误和异常扩展 Throwable

      查看 Throwable JavaDoc:

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

      【讨论】:

        【解决方案5】:

        正如其他海报所指出的,并非所有可投掷对象都是Exception 的子类。然而,在大多数情况下,捕获ErrorThrowable 并不是一个好主意,因为这些情况包括一些非常严重的错误情况,这些情况不容易恢复。您的恢复代码可能只会让事情变得更糟。

        【讨论】:

        • 是的。但是你可能还有更多的问题。例如如果/当你捕捉到 OutOfMemoryError 会发生什么?
        【解决方案6】:

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

        为了在编译时检查异常,Throwable 和 Throwable 的任何子类,但不是两者的子类 RuntimeException 或 Error 被视为已检查的异常。

        对我来说,将这个问题的答案视为已检查与未检查的异常(小写 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。这取决于上下文。

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            猜你喜欢
            • 2012-10-26
            • 2015-07-04
            • 1970-01-01
            • 2014-03-22
            • 1970-01-01
            • 2010-09-28
            • 2012-05-31
            相关资源
            最近更新 更多