Java:使用 return 尝试捕获资源并抛出新语句

Java: try-catch-resources with return and throw new statements

这是我的案例:

private ResultSetType makeRequest() {
    try (CloseableHttpResponse response = this.sendRequest(request)) {
        String responseBody = IOUtils.toString(
            response.getEntity().getContent(),
            StandardCharsets.UTF_8
        );
            
        if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
            // do something;
            return ...
        } else {
            throw new LoaderSystemFault(LoaderConstants.ErrorCodes.ERR_002, "Communication error with Servei Territorial (status-code: {0} / request: {1} / response: {2})", response.getStatusLine().getStatusCode(), request, responseBody);
        }
    } catch (IOException | JAXBException e) {
        throw new LoaderSystemFault(LoaderConstants.ErrorCodes.ERR_002, "Communication error with Servei Territorial (status-code: {0} / request: {1} / response: {2})", response.getStatusLine().getStatusCode(), request, responseBody);
    }
}

我的目标是关闭 CloseableHttpResponse

这里有几个问题:

我不清楚 CloseableHttpResponse 是否会关闭,无论是否达到 returnthow new 语句。

如何重构以上代码?

有什么想法吗?

根据 Java Language Specification,像您那里的那样的 try-with-resources 首先被翻译成:

try {
    try (CloseableHttpResponse response = this.sendRequest(request)) {
        String responseBody = IOUtils.toString(
            response.getEntity().getContent(),
            StandardCharsets.UTF_8
        );
            
        if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
            // do something;
            return ...
        } else {
            throw new LoaderSystemFault(LoaderConstants.ErrorCodes.ERR_002, "Communication error with Servei Territorial (status-code: {0} / request: {1} / response: {2})", response.getStatusLine().getStatusCode(), request, responseBody);
        }
    }
} catch (IOException | JAXBException e) {
    throw new LoaderSystemFault(LoaderConstants.ErrorCodes.ERR_002, "Communication error with Servei Territorial (status-code: {0} / request: {1} / response: {2})", response.getStatusLine().getStatusCode(), request, responseBody);
}

内部 try-with-with 资源现在是基本的 try-with-resources 语句,翻译如下:

{
    final CloseableHttpResponse response = this.sendRequest(request);
    Throwable #primaryExc = null;

    try {
        // everything in your try block
    } catch (Throwable #t) {
        #primaryExc = #t;
        throw #t;
    } finally {
        if (response != null) {
            if (#primaryExc != null) {
                try {
                    response.close();
                } catch (Throwable #suppressedExc) {
                    #primaryExc.addSuppressed(#suppressedExc);
                }
            } else {
                response.close();
            }
        }
    }
}

需要注意的重要一点是,原始 try-with-resources 中的块被转换为 try-catch-finally 的 try 块,资源的关闭是在finally块。

这意味着正常的 try-catch-finally 语句的语义在这里适用——如果 try 块突然完成(即 returns 或抛出)或者如果它正常完成,finally 被执行。有关详细信息,请参阅 §14.20.2。您会看到 finally 在规范中提到的每种情况下都会执行。

总之,即使达到 returnthrow,您的资源也将被关闭。