未捕获Java异常

时间:2009-09-03 18:25:53

标签: java exception try-catch

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

7 个答案:

答案 0 :(得分:116)

因为某些例外不是来自Exception - 例如ThrowableError

基本上,类型层次结构是:

       Object
         |
      Throwable
     /         \
Exception      Error

只能抛出Throwables和派生类,所以如果你抓住Throwable,那真的会抓住所有东西。

ThrowableException以及源自Exception 其他的任何异常,而不是RuntimeException派生的已检查异常 - 他们是你必须宣布你会抛出的东西,或者如果你打电话给它们就会抓住它们。

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

答案 1 :(得分:6)

Error不是Exception s。

  

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

- JavaDoc for java.lang.Exception

  

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

- JavaDoc for java.lang.Error

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

  

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

- JavaDoc for ThreadDeath

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

答案 2 :(得分:4)

异常只是一种Throwable; NoSuchMethodError不是Exception,而是Error,这是另一种Throwable。

答案 3 :(得分:3)

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

请参阅Throwable JavaDoc

  

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

答案 4 :(得分:1)

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

答案 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。这取决于具体情况。