簡體   English   中英

沒有抓到Java異常?

[英]Java exception not caught?

我對try-catch構造有一個小的理論問題。

我昨天參加了一個關於Java的實踐考試,我不明白以下例子:

try {
    try {
        System.out.print("A");
        throw new Exception("1");
    } catch (Exception e) {
        System.out.print("B");
        throw new Exception("2");
    } finally {
        System.out.print("C");
        throw new Exception("3");
    }
} catch (Exception e) {
    System.out.print(e.getMessage());
}

問題是“輸出會是什么樣子?”

我很確定它會是AB2C3,但令人驚訝的是,這不是真的。

正確的答案是ABC3(經過測試,確實就是這樣)。

我的問題是,例外(“2”)去了哪里?

來自Java語言規范14.20.2。

如果catch塊由於原因R突然完成,則執行finally塊。 然后有一個選擇:

  • 如果finally塊正常完成,則try語句突然完成,原因是R.

  • 如果finally塊因為原因S而突然完成,則try語句突然完成,原因是S(並且原因R被丟棄)

所以,當有一個引發異常的catch塊時:

try {
    // ...
} catch (Exception e) {
    throw new Exception("2");
}

但是還有一個finally塊也會引發異常:

} finally {
    throw new Exception("3");
}

Exception("2")將被丟棄,只傳播Exception("3")

finally塊中拋出的異常會抑制先前在try或catch塊中拋出的異常。

Java 7示例: http//ideone.com/0YdeZo

Javadoc的例子:


static String readFirstLineFromFileWithFinallyBlock(String path)
                                                     throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        if (br != null) br.close();
    }
}

但是,在此示例中,如果方法readLine和close都拋出異常,則方法readFirstLineFromFileWithFinallyBlock拋出finally塊拋出的異常; 從try塊拋出的異常被抑制。


Java 7的新try-with語法增加了另一個異常抑制步驟:try塊中拋出的異常會抑制try-with part中之前拋出的異常。

來自同一個例子:

try (
        java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
        java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {
        for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {
            String newLine = System.getProperty("line.separator");
            String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
            writer.write(zipEntryName, 0, zipEntryName.length());
        }
    }

可以從與try-with-resources語句關聯的代碼塊中拋出異常。 在上面的示例中,可以從try塊拋出異常,並且當try-with-resources語句嘗試關閉ZipFile和BufferedWriter對象時,最多可以拋出兩個異常。 如果從try塊拋出異常並且從try-with-resources語句拋出了一個或多個異常,那么從try-with-resources語句拋出的那些異常將被抑制,並且塊拋出的異常是這是由writeToFileZipFileContents方法拋出的。 您可以通過從try塊拋出的異常中調用Throwable.getSuppressed方法來檢索這些抑制的異常。


在問題的代碼中,每個塊明顯地丟棄舊的異常,甚至沒有記錄它,當你試圖解決一些錯誤時不好:

http://en.wikipedia.org/wiki/Error_hiding

throw new Exception("2"); catch塊拋出而不是try ,它不會被再次捕獲。
14.20.2。 執行try-finally和try-catch-finally

這就是發生的事情:

try {
    try {
        System.out.print("A");         //Prints A
        throw new Exception("1");   
    } catch (Exception e) { 
        System.out.print("B");         //Caught from inner try, prints B
        throw new Exception("2");   
    } finally {
        System.out.print("C");         //Prints C (finally is always executed)
        throw new Exception("3");  
    }
} catch (Exception e) {
    System.out.print(e.getMessage());  //Prints 3 since see (very detailed) link
}

您的問題非常明顯,答案很簡單。 消息為“2”的Exception對象被Exception對象覆蓋,消息為“3”。

說明:當發生異常時,拋出其對象以捕獲要處理的塊。 但是當catch塊本身發生異常時,其對象將被轉移到OUTER CATCH Block(如果有)以進行異常處理。 同樣的事發生在這里。 帶有消息“2”的異常對象被傳送到OUTER catch Block。 但是等等 ..在離開內部的try-catch塊之前,它已經執行了最終。 這里發生了我們關注的變化。 拋出一個新的EXCEPTION對象(帶有消息“3”)或者這個finally塊替換已經拋出的Exception對象(帶有消息“2”)。結果,當打印出Exception對象的消息時,我們得到了被覆蓋的值即“3”而不是“2”。

記住:CATCH塊只能處理一個異常對象。

finally塊總是運行。 要么從try塊內部return ,要么拋出異常。 finally塊中拋出的異常將覆蓋catch分支中拋出的異常。

此外,拋出異常不會導致任何輸出。 該行throw new Exception("2"); 不會寫任何東西。

根據你的代碼:

try {
    try {
        System.out.print("A");
        throw new Exception("1");   // 1
    } catch (Exception e) {
        System.out.print("B");      // 2
        throw new Exception("2");
    } finally {                     // 3
        System.out.print("C");      // 4 
        throw new Exception("3");
    }
} catch (Exception e) {             // 5
    System.out.print(e.getMessage());
}

正如你在這里看到的:

  1. 打印A並拋出異常# 1 ;
  2. 這個例外由catch語句和打印B - # 2捕獲;
  3. 最后塊# 3在try-catch之后執行(或者只是嘗試,如果沒有發生任何異常)語句並打印C - # 4並拋出新的異常;
  4. 這個被外部捕獲聲明# 5捕獲;

結果是ABC3 2是在相同的方式省略1

暫無
暫無

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

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