finally的兩種特性:
對於沒有垃圾回收和析構函數自動調用機制的語言來說,Java中的finally非常重要。它能使程序員保證:
1、無論異常是否被拋出,finally子句總能被執行。這個特性我們可以用來解決以下問題:Java的異常不允許我們回到異常拋出的地點時,該如何應對?把try塊放在循環里,建立了一個“程序繼續執行之前必須要達到”的條件。還可以加入一個static類型的計數器之類的裝置,使循環在放棄之前能嘗試一定的次數,這將使程序的健壯性更上一個台階。
2、無論try塊發生了什么,內存總能得到釋放。但Java有垃圾回收機制,所以內存釋放不再是問題,而且Java也沒有析構函數可供調用。那么,Java在什么情況下才能用到finally呢?
當要把除內存之外的資源恢復到它們的初始狀態時,就要用帶finally子句。這種需要清理的資源包括:已經打開的文件或網絡連接,在屏幕上畫的圖形,甚至是外部世界的某個開關。
可能導致異常丟失的兩種情況:
1、但是如果用某些特殊的方式使用finally子句,會導致異常丟失:
package com.test.exception.lost; public class VeryImportantException extends Exception{ public String toString() { return "A very important exception!"; } } package com.test.exception.lost; public class HoHumException extends Exception { public String toString() { return "A trivial exception"; } } package com.test.exception.lost; public class LostMessage { void f() throws VeryImportantException { throw new VeryImportantException(); } void dispose() throws HoHumException { throw new HoHumException(); } public static void main(String[] args) { try { LostMessage lm = new LostMessage(); try { lm.f(); } finally { lm.dispose(); } } catch(Exception e) { System.out.println(e); } } }
輸出中可以看到,VeryImportantException不見了,被finally子句里的HoHumException取代。這是相當嚴重的缺陷,C++把“前一個一場還沒處理完就拋出下一個異常”的情形看成是糟糕的編程錯誤。也許在Java的未來版本中(此處為JDK1.7)會修正這個問題。
2、一種更加簡單的異常丟失情況是從finally子句中返回:
package com.test.exception.lost; public class ExceptionSilencer { @SuppressWarnings("finally") public static void main(String[] args) { try { throw new RuntimeException(); } finally { return; } } }
如果運行這個程序,就會看到及時拋出了異常,也不會產生任何輸出。(這里就不貼運行結果的圖了,不會有任何輸出信息在控制台)
總結:
finally對於保證程序的正確性有很大的用處,但是使用過程中要注意避免以下兩種會導致異常丟失的情況(起碼在JDK1.7是這樣的)
1、在finally子句中拋出異常;
2、在finally子句中返回(return)。