簡體   English   中英

異常在調用堆棧中傳播

[英]Exceptions propagate up Call Stack

我很難理解讓異常在調用堆棧中傳播的概念或真正的用處。 我知道如何創建它們,但是我真的不知道何時使用它們,就像在一個簡單的現實世界中的數學應用程序中一樣。

public void method1(){
    try{
        method2();
    }
    catch(Exception e){
        e.printStackTrace();
    }
}

public void method2(){
      try{
          throw new Exception();
      }
      finally{
         System.out.println("no exception, try cleanup");
      }
}

我認為這基本上是它的工作方式,盡管它可能更多地涉及更多的異常和函數,但是我並沒有真正使用它們而不是僅僅捕獲每個函數的意義。

...但是我真的不明白使用這些方法的意義,而不僅僅是在每個函數中都有問題。

關鍵是調用棧中的下一個函數可能不知道如何處理該異常。 例:

public class Test {

    public Object doSomething(String source) throws IOException {
        try (InputStream is = openAsStream(source)) {
            // ... read and process stuff
            return ...
        }
    }

    public InputStream openAsStream(String name) throws IOException {
        String fileName = // ... do something with 'name'
        return new FileInputStream(name);
    }

    public static void main(String[] args) {
        // ...
        Test t = new Test();
        try {
            t.doSomething(args[0]);
        } catch (IOException ex) {
            System.err.println("Cannot handle '" + args[0] + "'");
        }
    }
}

openAsStream調用FileInputStream構造函數,該構造函數可能會拋出IOException openAsStream方法無法從中恢復,因此它可以傳播。 doSomething方法也不知道如何處理,因此它可以傳播。 最后,異常到達main ...,它知道如何向用戶解釋問題。


現在您可以編寫openAsStream來捕獲IOException ,打印一條錯誤消息並返回null 但這將是一個大錯誤:

  • openAsStream()不(也不應該 )知道是否/如何向用戶報告問題。

  • 並且,如果它向調用方返回null ,則調用方必須進行測試以查看調用結果是否為null ...並采取替代措施。

關鍵是方法只應處理可以在該級別上適當處理的異常。 應該允許其他人傳播。 (或者包裹在另一個異常中……如果那是API設計所要求的。)

有時,生成異常的代碼不知道如何正確處理它。 如果您在一段事務代碼中,並且發生了故障,那么該方法/組件可能無法做更多的事情,而不僅僅是在嘗試處理該異常時記錄該異常。 另一方面,一層或多層可以嘗試重新建立連接,或向請求者提供詳細的錯誤響應。

通常,調用者具有適當的上下文來處理問題,而執行生成異常的操作的代碼則沒有。 假設我是一個高級程序,希望將一些數據寫到文件中。 我正在調用的低層服務,我們稱它為writeFile()可以由於多種原因引發IOException。

寫writeFile()的人不會知道將在哪個上下文中使用writeFile()。 如果writeFile()失敗,是否應該嘗試重新寫入文件? 它應該嘗試幾次? 它應該放棄嗎? 因為在完成某些任務的方案中編寫低級函數writeFile()的上下文的程序員陷入了困境,所以程序員無法預期調用者將如何處理錯誤情況。

而不是試圖猜測調用者將如何處理錯誤(一項不可能的任務),writeFile()的程序員向調用writeFile()的客戶端指示了一些“未解決的問題”,當問題出現時需要回答出現。 每個問題都由一個異常類指示,當客戶程序員捕獲到該異常時,客戶程序員將使用客戶程序員永遠都不會希望擁有的上下文來寫一個未解決問題的答案。

簡而言之,如果您曾經看到一個列出了已檢查異常的方法,則編寫該異常的程序員會說:“ Whomever調用此方法將具有適當的上下文,可以決定對該異常情況如何處理。我不會。”

默認情況下,異常傳播使您的代碼對錯誤進行快速失敗檢查。

考慮異常傳播的替代方法-返回錯誤代碼。 如果代碼的調用者無意或有意地未測試錯誤代碼,則他們可以使用您的方法,不知道您的對象現在處於無法使用的狀態,並繼續調用方法並導致未定義的行為/內存損壞。 如果您引發了異常,那么如果調用者忘記捕獲異常,那么它們就不會做可怕的事情,而是迅速失敗,並且可以向程序員發出有關拋出該異常的原因,原因和處理方法的警報。 異常大聲且令人討厭,因為它們表示需要考慮的條件。

暫無
暫無

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

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