在扩展的try-with-resources语句中究竟抓到了什么?

Enr*_*que 6 java error-handling try-catch try-with-resources

在以下代码块中:

try ( /* resources declaration */ ) {
    // some dangerous code
} catch (Exception e) {
    // error handling and reporting
}
Run Code Online (Sandbox Code Playgroud)

如果会发生什么,在里面的代码try块和自动close()声明抛出异常?哪一个会陷入困境catch?他们都?只有其中一个?如果是这样,哪一个?

如果try成功但close不是?是否会输入捕获块?

Tun*_*aki 6

引用JLS第14.20.3.1节:

在管理单个资源的基本try-with-resources语句中:

  • 如果资源的初始化由于throw某个值而突然完成V,那么try-with-resources语句会因为某个throw值而突然完成V.
  • 如果资源的初始化正常完成,并且try由于throw某个值而导致块突然完成V,则:

    • 如果资源的自动关闭正常完成,那么try-with-resources语句会因为某个throw值而突然完成V.

    • 如果由于throw某个值而导致资源的自动关闭突然完成V2,那么try-with-resources语句会因为添加到被抑制的异常列表中throw的值V而突然完成.V2V

  • 如果资源的初始化正常完成,并且try块正常完成,并且由于抛出值而导致资源的自动关闭突然完成V,则try-with-resources语句由于throw值的一个而突然完成V.

这意味着如果try块内的代码和自动close()语句都抛出异常,则该catch部件将处理try块抛出的异常,close()并在抑制的异常中抛出异常.

此外,这意味着如果try块成功但自动close()失败,catch则会执行,并且捕获的异常将是抛出的异常close().


这是验证此行为的测试:

public class Main {
    public static void main(String[] args) throws Exception {
        // try block fails and close() fails
        try (T t = new T()) {
            throw new Exception("thrown by try part");
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e.getSuppressed()[0].getMessage());
        }

        // try block is successful but close() fails
        try (T t = new T()) {
            //
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

class T implements AutoCloseable {
    @Override
    public void close() throws Exception {
        throw new Exception("thrown by close");
    }
}
Run Code Online (Sandbox Code Playgroud)

此代码将打印出来

thrown by try part
thrown by close
thrown by close
Run Code Online (Sandbox Code Playgroud)

意味着catched异常是第一部分的代码的try部分抛出的异常.对于第二部分,捕获的异常确实是抛出的异常close().