三. 以finally進行清理
1. 如果某段代碼不管是否發生異常都要執行,那可把它改入finally塊中。
import java.sql.SQLException; class TestException{ public static void tSql() throws SQLException { System.out.println("Originating the exception in tSql()"); throw new SQLException("throw in tSql"); } public void f() throws SQLException{ try{ tSql(); } catch(SQLException ex){ System.out.println("catch SQLException in f()"); throw ex;//(1)
} finally{ System.out.println("finally in f()"); } } } public class Test{ public static void main(String[] args){ TestException te = new TestException(); try{ te.f(); } catch(SQLException ex){ System.out.println("catch te.f() SQLException in main"); } catch(Exception ex){ System.out.println("catch te.f() Exception in main"); } } } 運行結果為:
Originating the exception in tSql()
catch SQLException in f()
finally in f()
catch te.f() SQLException in main 雖然在代碼(1)處重新拋出異常,但finally塊中的代碼仍然會被執行。
2. finally造成的異常遺失
如果在finally中執行的代碼又產生異常,那么在上一層調用中所捕捉到的異常的起始拋出點會是finally所在的函數。
import java.sql.SQLException; class TestException{ public static void tSql1() throws SQLException { System.out.println("Originating the exception in tSql()"); throw new SQLException("throw in tSql1"); } public static void tSql2() throws SQLException { System.out.println("Originating the exception in tSql()"); throw new SQLException("throw in tSql2"); } public void f() throws SQLException{ try{ tSql1(); } catch(SQLException ex){ System.out.println("catch SQLException in f()"); throw ex;//(2)
} finally{ System.out.println("finally in f()"); //tSql2();(1)
} } } public class Test{ public static void main(String[] args){ TestException te = new TestException(); try{ te.f(); } catch(SQLException ex){ System.out.println("catch te.f() SQLException in main"); System.out.println("getMessage:" + ex.getMessage()); System.out.println("printStackTrace:"); ex.printStackTrace(); } } } 運行結果為:
Originating the exception in tSql()
catch SQLException in f()
finally in f()
catch te.f() SQLException in main getMessage:throw in tSql1 printStackTrace:
java.sql.SQLException: throw in tSql1 void TestException.tSql1()
Test.java:5 void TestException.f()
Test.java:13 void Test.main(java.lang.String[])
Test.java:29 從結果可以看出,在main()中能正確打印出所捕捉到的異常的起始拋出點。但如果去掉代碼(1)的注釋,結果將變為:
Originating the exception in tSql()
catch SQLException in f()
finally in f()
Originating the exception in tSql()
catch te.f() SQLException in main getMessage:throw in tSql2 printStackTrace:
java.sql.SQLException: throw in tSql2 void TestException.tSql2()
Test.java:9 void TestException.f()
Test.java:21 void Test.main(java.lang.String[])
Test.java:29 從結果可以看出,在main()中捕捉到的異常是finally中產生的異常,代碼(2)中拋出的異常丟失了。
|