2010-06-30 80 views
8

我想下面的例子;但無法弄清楚finally塊的重要性。你能告訴我這兩個代碼示例執行的區別嗎?另外一個真實的例子可能會有所幫助。Java中finally塊的要點是什麼?

示例1:

try{ 
     // some code 1 
    }catch(Exception ex){ 
     // print exception 
    }finally{ 
     // some code 2    
    } 

示例2:

try{ 
     // some code 1 
    }catch(Exception ex){ 
     // print exception 
    } 
    // some code 2 
+0

請注意,這是很少有用到有一個'既具有'catch'和try'聲明如果你不想要混亂的代碼,「最後」。 – 2010-06-30 09:26:33

+0

@Tom爲什麼呢?它們服務於2個完全不同的目的,捕捉是處理失敗,最後是資源處理。 – james 2010-06-30 16:47:07

+0

@james是的,他們有完全不同的用途,這意味着他們的範圍通常應該不同。 – 2010-06-30 17:05:16

回答

17

您提供的兩個片段有很大的不同,當catch塊本身引發異常時,finally塊仍將由其語義執行。

了下面的片斷輸出"Finally!",但不"What about me???"

try { 
     throw null;  // throws NullPointerException! 
    } catch (Exception e) { 
     int oops = 1/0; // throws ArithmeticException! 
    } finally { 
     System.out.println("Finally!"); // still gets executed! 
    } 
    System.out.println("What about me???"); // doesn't get executed! 

一般來說,try實際上總是被執行的finally。對try區塊後面的任何代碼都沒有這樣的保證。


但如果我的catch塊只是一個簡單的print聲明什麼呢?

目前仍然不能保證它不會throw東西。例如,某些東西仍然可能會出錯。爲例外詳細信息的構建。

即使您盡最大努力保證catch代碼是「安全」且try語句後面的代碼將始終執行,那麼問題就會變成「爲什麼?」。爲什麼要避免finally,但然後努力複製它的語義?

finally語義是有保證的,不需要編寫者或代碼讀者的證明責任。正因爲如此,這是慣用的使用finally塊來強制性的「清理」代碼。使用finally可確保正確性並增強可寫性和可讀性。

+0

有想法。在我只是調用catch塊中的打印函數的情況下,最後沒有任何重要性? – abuzittin 2010-06-30 09:03:23

+0

@abuzittin:超過語義,PATTERN本身很重要。 '終於'把強制性的清理代碼放在地上是很習慣的。 「finally」語義使得意圖更清晰。另外,在某些情況下,一個簡單的打印可能會引發異常(例如'IOException',記錄器變得焦急,消息建立出錯等)。 – polygenelubricants 2010-06-30 09:06:16

+1

請注意,如果發生災難性事件(例如:用戶殺死進程或拔掉機器),它仍然可能無法執行,但就異常情況而言,您還可以。 – 2010-06-30 10:59:04

2

您使用finally塊,以清理和運行應該運行的異常是否被拋出(和捕獲)任何代碼或不。這包括您在catch區塊中的代碼。

+0

你的意思是說,如果我有catch塊代碼可以拋出異常?在我只調用打印函數的情況下,最後沒有任何重要性? – abuzittin 2010-06-30 08:57:13

8

finally塊即使在例如,一個Error被拋出,在你的例子中沒有被catch塊捕獲。因此,無論trycatch塊中的操作結果如何,您都可以將清理代碼放入finally塊中,該塊應運行總是

請注意,通常catch塊會捕獲更多特定類型的異常 - 通常只檢查異常 - 所以在大多數情況下,上述兩個代碼示例之間的差異非常明確。

更新:你可以說你的catch塊永遠不會拋出異常,所以finally是不需要的。但是,請注意兩兩件事:

  • 這只是當前代碼的狀態,它可以在未來改變 - 你能保證未來的程序員誰在catch增加了一些潛在的異常拋出代碼塊,會記得把它之後的清理代碼放到finally塊中?
  • try-catch-finally編程習慣用法這使得閱讀代碼的人更容易理解正在發生的事情。如果你不使用常用的習慣用語,那麼你就會冒着誤解的風險,從而長期存在錯誤。
+0

異常或錯誤。如果我們用錯誤而不是異常來重新思考我的問題,你的答案是什麼? – abuzittin 2010-06-30 08:58:58

+0

感謝您的更新部分。 – abuzittin 2010-06-30 09:07:39

+0

@abuzittin,我在此期間更新了我的帖子,我相信這會回答你的問題。順便說一句,它應該是'Throwable',而不是'Error'。 – 2010-06-30 09:07:50

1

當我們想釋放try塊中使用的資源時,這很有幫助。所以唯一不會丟失的地方最終會被封鎖。因爲如果拋出異常,java不會執行那之後立即執行的代碼。它直接跳到catch塊。

0

請注意,您可以去嘗試,最後沒有一個問題:

try{ 
    // some code 
}finally{ 
    // cleanup code 
} 

一個例子,因此可能是想例外傳播給調用者的方法,但仍需要清理代碼,例如釋放看。

0

如果try塊中的語句拋出未經檢查的異常,finally塊將被執行,允許程序員執行相關操作。

0

在現實生活中,finally塊用於關閉打開的資源,即使發生異常。 例如,當你當你訪問一個數據庫中讀取(或寫)的文件,等

public void readFile(String fileName) { 
    FileReader fr; 
    BufferedFileReader bfr; 

    try { 
     fr = new FileReader(fileName); 
     bfr = new BufferedFileReader(fr); 
     // ... 
    } catch (IOException ioe) { 
     // ... 
    } finally { 
     // TO ENSURE THAT THE READERS ARE CLOSED IN ALL CASES 
     if (bfr != null) { 
      try { 
       bfr.close(); 
      } catch (IOException ignoredIOE) {} 
     } 
     if (fr != null) { 
      try { 
       fr.close(); 
      } catch (IOException ignoredIOE) {} 
     } 
    } 
} 
相關問題