Java使用try-catch捕获异常

示例

可以使用该try...catch语句捕获和处理异常。(实际上,try语句采用其他形式,如关于try...catch...finally和的其他示例所述try-with-resources。)

尝试捕获一个捕获块

最简单的形式如下:

try {
    doSomething();
} catch (SomeException e) {
    handle(e);
}
// 下一个陈述

一个简单的行为try...catch如下:

  • try执行块中的语句。

  • 如果该try块中的语句未引发任何异常,则控制传递到之后的下一个语句try...catch。

  • 如果在该try块内引发异常。

    • 该变量e绑定到异常对象。

    • catch执行该块中的代码。

    • 如果该代码引发异常,那么将传播新引发的异常以代替原始异常。

    • 否则,控制权传递到try...catch。之后的下一条语句。

    • 测试异常对象以查看其是实例SomeException还是子类型。

    • 如果是,则该catch块将捕获异常:

    • 如果不是,则原始异常继续传播。

    尝试捕获与多个捕获

    一个try...catch也可以有多个catch块。例如:

    try {
        doSomething();
    } catch (SomeException e) {
        handleOneWay(e)
    } catch (SomeOtherException e) {
        handleAnotherWay(e);
    }
    // 下一个陈述

    如果有多个catch块,则从第一个块开始一次尝试一次,直到找到匹配的例外。执行相应的处理程序(如上所述),然后将控制权传递给该语句之后的下一个try...catch语句。即使处理程序代码抛出异常catch,始终会跳过与之匹配的块之后的块。

    “自上而下”的匹配策略会对catch块中的异常没有脱节的情况产生影响。例如:

    try {
        throw new RuntimeException("test");
    } catch (Exception e) {
        System.out.println("Exception");
    } catch (RuntimeException e) {
        System.out.println("RuntimeException");
    }

    此代码段将输出“ Exception”,而不是“ RuntimeException”。由于RuntimeException是的子类型Exception,因此第一个(更一般)catch会被匹配。第二个(更具体的)catch将永远不会执行。

    从中学到的教训是,最具体的catch块(就异常类型而言)应该首先出现,而最一般的块应该位于最后。(如果acatch永远无法执行,则某些Java编译器会警告您,但这不是编译错误。)

    多例外捕获块

    Java SE 7

    从Java SE 7开始,单个catch块可以处理一系列不相关的异常。列出了例外类型,并用竖线(|)符号分隔。例如:

    try {
        doSomething();
    } catch (SomeException | SomeOtherException e) {
        handleSomeException(e);
    }

    多异常捕获的行为是单异常情况的简单扩展。本catch场比赛,如果抛出的异常匹配(至少)列出的例外之一。

    规范中还有一些其他细微之处。的类型e是列表中异常类型的综合联合。使用的值时e,其静态类型是类型并集的最不常见的超类型。但是,如果e在catch块内重新抛出,则抛出的异常类型是联合中的类型。例如:

    public void method() throws IOException, SQLException
        try {
            doSomething();
        } catch (IOException | SQLException e) {
            report(e);
            throw e;
        }

    在上述IOException和SQLException中,检查了最不常见的超类型为的异常Exception。这意味着该report方法必须匹配report(Exception)。但是,编译器知道throw只能抛出IOException或SQLException。因此,method可以声明为throws IOException, SQLException而不是throws Exception。(这是一件好事:请参阅陷阱-Throwing Throwable,Exception,Error或RuntimeException。)