簡體   English   中英

為什么在這種情況下允許拋出已檢查的異常類型?

[英]Why is throwing a checked exception type allowed in this case?

我偶然注意到這個throw語句(從一些更復雜的代碼中提取)編譯:

void foo() {
    try {

    } catch (Throwable t) {
        throw t;
    }
}

對於一個短暫而快樂的時刻,我認為已經檢查過的異常最終決定已經死了,但它仍然在這方面很高興:

void foo() {
    try {

    } catch (Throwable t) {
        Throwable t1 = t;
        throw t1;
    }
}

try塊不必為空; 它似乎可以有代碼,只要該代碼不會拋出已檢查的異常。 這似乎是合理的,但我的問題是,語言規范中的哪些規則描述了這種行為? 據我所知§14.18town語句明確禁止它,因為t表達式的類型是一個已檢查的異常,並且它沒有被捕獲或聲明被拋出。 (?)

這是因為Java 7中引入的Project Coin中包含的更改允許通過重新拋出原始異常來進行常規異常處理。 這是一個適用於Java 7但不適用於Java 6的示例:

public static demoRethrow() throws IOException {
    try {
        throw new IOException("Error");
    }
    catch(Exception exception) {
        /*
         * Do some handling and then rethrow.
         */
        throw exception;
    }
}

您可以在此處閱讀解釋更改的整篇文章。

我認為,在措辭§14.18的throw聲明 ,你指的是在JLS一個錯誤-應該已經更新了Java SE 7中,而不是文字。

描述預期行為的JLS文本位於第11.2.2節語句的異常分析中

throw語句表達式是catch子句C的最終或有效最終異常參數的throw語句可以拋出異常類E iff:

  • E是一個異常類,聲明C的try語句的try塊可以拋出;
  • E的賦值與C的任何可捕獲異常類兼容;
  • E與同一try語句中在C左側聲明的catch子句的任何可捕獲異常類不兼容。

第一個要點是相關要點; 因為catch -clause參數t是有效的最后(這意味着它從未分配或增加或減少;見§4.12.4 final變量 ), throw t只能扔東西的try塊可以拋出。

但正如您所說,§14.18中的編譯時檢查不會對此作出任何限制。 §11.2.2不決定允許什么,不允許什么; 相反,它應該是對可以拋出的各種限制的后果的分析。 (這種分析確實反饋到規范的更規范的部分 - §14.18本身在其第二個子彈點中使用它 - 但§14.18不能只說“如果它拋出一個它不能的例外它是編譯時錯誤拋出§11.2.2“,因為這將是循環的。)

所以我認為需要調整§14.18以適應§11.2.2的意圖。

很好找!

11.2中的JLS中詳細描述了此行為 編譯時檢查例外

throw語句表達式是catch子句C的最終或有效最終異常參數的throw語句可以拋出異常類E iff:

  • E是一個異常類,聲明C的try語句的try塊可以拋出 ;

  • E的賦值與C的任何可捕獲異常類兼容;

  • E與同一try語句中在C左側聲明的catch子句的任何可捕獲異常類不兼容。

(強調我的。)

您的第二個示例失敗,因為t1不是“ catch子句的異常參數”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM