04-異常處理-動手動腦
1.請閱讀並執行AboutException.java示例,然後通過後面的幾頁PPT瞭解Java中實現異常處理的基礎知識。
import javax.swing.*; class AboutException { public static void main(String[] a) { int i=1, j=0, k; k=i/j; try { k = i/j; // Causes division-by-zero exception //throw new Exception("Hello.Exception!");} catch ( ArithmeticException e) { System.out.println("被0除. "+ e.getMessage()); } catch (Exception e) { if (e instanceof ArithmeticException) System.out.println("被0除"); else { System.out.println(e.getMessage()); } }finally { JOptionPane.showConfirmDialog(null,"OK"); } } }
其輸出以下結果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ketangceshi.AboutException.main(AboutException.java:9)
有關異常處理的知識:
處理機制:吧可能發生錯誤的程式碼放入try語句塊中,當程式檢測到出現了一個錯誤時會丟擲一個異常物件。異常處理程式碼會捕獲並處理這個錯誤(catch語句塊中的程式碼用於處理錯誤)。當異常發生時,程式控制流程由try語句塊跳轉到catch語句塊。不管是否有異常發生,finally語句塊中的語句始終保持被執行。如果沒有提供合適的異常處理程式碼,JVM將會結束掉整個應用程式。
異常分類:Throwable類有兩個直接子類: Exception:出現的問題是可以被捕獲的; Error:系統錯誤,通常由JVM處理。 可捕獲的異常又可以分為兩類: (1)Check異常:直接派生自Exception的異常類,必須被捕獲或再次宣告丟擲 (2)Runtime異常:派生自RuntimeException的異常類。使用throw語句可以隨時丟擲這種異常物件: throw new ArithmeticException(…);
上述情況出現的原因:異常處理有“多型”的特性。
異常多型特性
可以有多個catch語句塊,每個程式碼塊捕獲一種異常。在某個try塊後有兩個不同的catch 塊捕獲兩個相同型別的異常是語法錯誤。 使用catch語句,只能捕獲Exception類及其子類的物件。因此,一個捕獲Exception物件的catch語句塊可以捕獲所有“可捕獲”的異常。 將catch(Exception e)放在別的catch塊前面會使這些catch塊都不執行,因此Java不會編譯這個程式。
finally的功能
資源洩露:當一個資源不再被某應用程式使用,但此程式並未向系統宣告不再使用此資源時發生這種情況 finally語句塊主要用於解決資源洩露問題,它位於catch語句塊之後,JVM保證它們一定執行。 注意:finally語句塊中也可能發生異常,如果這種情況發生,先前的異常被放棄。
2.多層的異常捕獲-1
public class CatchWho { public static void main(String[] args) { try { try { throw new ArrayIndexOutOfBoundsException(); } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/內層try-catch"); } throw new ArithmeticException(); } catch(ArithmeticException e) { System.out.println("發生ArithmeticException"); } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/外層try-catch"); } } }
執行結果如下:
3.多層的異常捕獲-2
public class CatchWho2 { public static void main(String[] args) { try { try { throw new ArrayIndexOutOfBoundsException(); } catch(ArithmeticException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/內層try-catch"); } throw new ArithmeticException(); } catch(ArithmeticException e) { System.out.println("發生ArithmeticException"); } catch(ArrayIndexOutOfBoundsException e) { System.out.println( "ArrayIndexOutOfBoundsException" + "/外層try-catch"); } } }
執行結果如下:
4.動手動腦:當有多個巢狀的try...catch...finally時,要特別注意finally的執行時機。
public class EmbededFinally { public static void main(String args[]) { int result; try { System.out.println("in Level 1"); try { System.out.println("in Level 2"); // result=100/0; //Level 2 try { System.out.println("in Level 3"); result=100/0; //Level 3 } catch (Exception e) { System.out.println("Level 3:" + e.getClass().toString()); } finally { System.out.println("In Level 3 finally"); } // result=100/0; //Level 2 } catch (Exception e) { System.out.println("Level 2:" + e.getClass().toString()); } finally { System.out.println("In Level 2 finally"); } // result = 100 / 0; //level 1 } catch (Exception e) { System.out.println("Level 1:" + e.getClass().toString()); } finally { . System.out.println("In Level 1 finally"); } } }
執行結果如下:
當有多層巢狀的finally時,異常在不同的層次丟擲,在不同的位置丟擲,可能會導致不同的finally語句塊執行順序。
5.finally語句塊一定會執行嗎?
public class SystemExitAndFinally { public static void main(String[] args) { try{ System.out.println("in main"); throw new Exception("Exception is thrown in main"); //System.exit(0); } catch(Exception e) { System.out.println(e.getMessage()); System.exit(0); } finally { System.out.println("in finally"); } } }
執行結果如下:
由執行結果分析得,finally語句塊中得內容不一定會執行。
6.如何跟蹤異常的傳播路徑?
// UsingExceptions.java // Demonstrating the getMessage and printStackTrace // methods inherited into all exception classes. public class PrintExceptionStack { public static void main( String args[] ) { try { method1(); } catch ( Exception e ) { System.err.println( e.getMessage() + "\n" ); e.printStackTrace(); } } public static void method1() throws Exception { method2(); } public static void method2() throws Exception { method3(); } public static void method3() throws Exception { throw new Exception( "Exception thrown in method3" ); } }
執行結果如下:
當程式中出現異常時,JVM會依據方法呼叫順序依次查詢有關的錯誤處理程式。 可使用printStackTrace 和 getMessage方法瞭解異常發生的情況: printStackTrace:列印方法呼叫堆疊。 每個Throwable類的物件都有一個getMessage方法,它返回一個字串,這個字串是在Exception建構函式中傳入的,通常讓這一字串包含特定異常的相關資訊。