Java 异常抛出自省

Java Exception-throwing introspection

我有一个关于 Java 方法内省的问题,特别是关于异常的问题。假设我有以下代码:

private String getCustomReportResponse(HttpsURLConnection customReportConnection) {
    int responseCode = 0;

    try {
        responseCode = customReportConnection.getResponseCode();
        return httpResponseBodyExtractor.extractResponseBodyFrom(customReportConnection);
    } catch (IOException e) {
        translateIntoRelevantException(responseCode, e);
    }
}

假设 try 块中的两个语句都能够抛出 IOException - 在这种情况下,将调用 translateIntoRelevantException 方法,如下所示:

private void translateIntoRelevantException(int responseCode, IOException e) {
    if(is5xxResponseCode(responseCode)) {
        throw new ServerResponseException("Could not generate report - returned response code " + responseCode, e);
    }

    throw new ReportException("GeminiReportException: Unable to parse response from HTTP body when requesting custom Gemini report.", e);
}

因此,无论发生什么情况,要么 returned 字符串,要么抛出异常。除了 getCustomReportResponse 方法不在 catch 块后添加 return 语句就无法编译,这是绝对无法访问的。事实上,如果我将 translateIntoRelevantException 的内容放入 catch 块中,它会编译,这对我来说似乎很愚蠢。

我应该补充一下,抛出的异常是运行时异常,但我也试过让它们成为检查异常,但问题仍然存在。

谁能解释一下为什么?

这是 "rethrow" 辅助方法所面对的 common problem

编译器不知道(也没有办法表明)方法 translateIntoRelevantException 永远不会 return.

因此,它认为 code-path 在 try 块之后继续。所以你必须输入 "dead-code" return null (或 throw new RuntimeException("should never come here").

不必放在try块之后,可以放在catch.

块里面
try {
    responseCode = customReportConnection.getResponseCode();
    return httpResponseBodyExtractor.extractResponseBodyFrom(customReportConnection);
} catch (IOException e) {
    translateIntoRelevantException(responseCode, e);
    throw new RuntimeException("should never come here");
}

让助手只 return 异常而不是抛出它可能更漂亮。然后你可以做

 throw translateIntoRelevantException(responseCode, e);

getCustomReportResponse 的编译不应依赖于 translateIntoRelevantException 的实现,原因有多种:

  • translateIntoRelevantException 的实现可能不可用(它可能在单独的 class 中,在单独的库中);
  • 否则 translateIntoRelevantException 中的任何更改都可能破坏所有调用方法。

作为替代方案,您可以 return 一个异常,然后将其抛出到客户端代码中:

private IOException translateIntoRelevantException(int responseCode, IOException e) {
    if(is5xxResponseCode(responseCode)) {
        return new ServerResponseException("Could not generate report - returned response code " + responseCode, e);
    }

    return new ReportException("GeminiReportException: Unable to parse response from HTTP body when requesting custom Gemini report.", e);
}

然后这样称呼它:

throw translateIntoRelevantException(responseCode, e);