天天看點

java中finally語句塊注意事項

 我在程式中使用TarArchiveOutputStream對多個檔案進行打包,finally語句塊中調用了它的close方法關閉輸出流。昨天碰到了一個很詭異的問題,執行到finally語句塊抛出異常。按正常處理邏輯,檔案打包會正常完成,finally中是不會出現異常的。然後就開始定位為什麼會出現這樣的異常,最終發現是因為打包過程中進行了額外的檢查,如果條件不符合就抛出異常,然後進入到finally語句塊。因為打包被異常中斷,導緻close出現異常,而finally中的異常會覆寫try語句中的異常,這就是我們定位這個檔案花了較長時間的原因。我們用一個簡單的測試代碼來重制和說明這個現象: 1. public class Test { 2.         public static void main(String[] args) { 3.                 int x = 1; 4.                 int y = 0; 5.                 int z; 6.                 try { 7.                         z = (100 * x) / y; 8.                         System.out.println("z=" + z); 9.                 } finally { 10.                         z = x / y; 11.                         System.out.println("z=" + z); 12.                 } 13.         } 14. } 可以看到第7行和第10行都會出現被0除的異常。 執行以上代碼的輸出結果: Exception in thread "main" java.lang.ArithmeticException: / by zero           at Test.main(Test.java:10) 可以看到沒有列印出第7行抛出異常時的調用堆棧。這是為什麼呢? 第7行抛出異常後,進入第9行開始的finally語句塊,finally語句塊中的第10行也出現了異常,導緻前面的異常被覆寫掉,是以最後列印出的異常調用堆棧是第10行的。 解決方法,捕獲finally中可能出現的異常,修改後代碼為: 1. public class Test { 2.         public static void main(String[] args) { 3.                 int x = 1; 4.                 int y = 0; 5.                 int z; 6.                 try { 7.                         z = (100 * x) / y; 8.                         System.out.println("z=" + z); 9.                 } finally { 10               try { 11.                 z = x / y; 12.                 System.out.println("z=" + z); 13.               } catch(Exception ex) { 14.                   ex.printStackTrace(); 15.               } 16.                 } 17.         } 18. }

執行時的輸出為: java.lang.ArithmeticException: / by zero           at Test.main(Test.java:11) Exception in thread "main" java.lang.ArithmeticException: / by zero           at Test.main(Test.java:7) 可見,這時try語句中的異常資訊也出來了。

總結一下,finally中的語句,如果可能出現異常,一定要catch。 另外一個規範的做法,不要在finally中return一個傳回值。具體原因是什麼,請各位仔細思考一下,相信會想明白的