1. 拋出異常•通過throw new ThrowableClass語法可以拋出一個異常,其中ThrowableClass是一個從Throwable繼承的類,或者是Throwable類本身,先看下面的 view plaincopy to clipboardprint? 01.public void proc(){ 02. // Exception是Throwable的繼承類,代表最基本的異常 03. throw new Exception("hello"); 04.} public void proc(){ // Exception是Throwable的繼承類,代表最基本的異常 throw new Exception("hello"); } •上面的代碼會導(dǎo)致編譯錯誤,對于有拋出異常的方法,編譯器強(qiáng)制要求:要么在方法上聲明要拋出的異常(稱為異常說明),要么在方法中用try塊捕獲這個異常。 view plaincopy to clipboardprint? 01.// 用異常說明,說明該方法要拋出的異常 02.public void proc() throws Exception{ 03. throw new Exception("hello"); 04.} 05. 06.// 用try塊捕獲該異常 07.public void proc(){ 08. try { 09. throw new Exception("hello"); 10. } catch (Exception e) { 11. e.printStackTrace(); 12. } 13.} // 用異常說明,說明該方法要拋出的異常 public void proc() throws Exception{ throw new Exception("hello"); } // 用try塊捕獲該異常 public void proc(){ try { throw new Exception("hello"); } catch (Exception e) { e.printStackTrace(); } } 異常說明可以是方法拋出的異常類本身,也可以是異常類的基類,比如throws后面可以是throwable。•上面說到對于有拋出異常的方法,必須帶有方法聲明,這并不準(zhǔn)確,當(dāng)拋出的異常類是RuntimeException或其繼承類時(shí),不需要異常說明: view plaincopy to clipboardprint? 01.// RuntimeException或其繼承類不需要異常聲明 02.public void proc(){ 03. throw new RuntimeException("hello"); 04.} // RuntimeException或其繼承類不需要異常聲明 public void proc(){ throw new RuntimeException("hello"); } •一個方法即使內(nèi)部沒有拋出異常,也仍然可以帶有異常說明: view plaincopy to clipboardprint? 01.public void proc2() throws NullPointerException, FileNotFoundException { 02.} public void proc2() throws NullPointerException, FileNotFoundException { } •一個方法若帶有異常說明,則調(diào)用它的其他方法也要帶有異常說明,或者要捕獲可能拋出的異常: view plaincopy to clipboardprint? 01.class A { 02. public void proc() throws Exception { 03. throw new Exception("hello"); 04. } 05. // 異常聲明 06. public void proc1() throws Exception { 07. proc(); 08. } 09. // 異常聲明,聲明中的類可以是基類 10. public void proc2() throws Throwable { 11. proc(); 12. } 13. // 直接捕獲異常 14. public void proc3() { 15. try { 16. proc(); 17. } catch (Exception e) { 18. e.printStackTrace(); 19. } 20. } 21.} class A { public void proc() throws Exception { throw new Exception("hello"); } // 異常聲明 public void proc1() throws Exception { proc(); } // 異常聲明,聲明中的類可以是基類 public void proc2() throws Throwable { proc(); } // 直接捕獲異常 public void proc3() { try { proc(); } catch (Exception e) { e.printStackTrace(); } } } •可以基于Exception現(xiàn)實(shí)自己的異常類: view plaincopy to clipboardprint? 01.class MyException1 extends Exception { 02.} 03.class MyException2 extends Exception { 04.} 05.class A { 06. public void proc() throws MyException1, MyException2{ 07. } 08.} class MyException1 extends Exception { } class MyException2 extends Exception { } class A { public void proc() throws MyException1, MyException2{ } } 2. 捕獲異常和結(jié)束清理•用try{}塊包圍住可能引發(fā)異常的代碼,后面緊跟著異常處理器(即catch(...){}塊);catch塊可以有多個,()中聲明要捕獲的異常類。當(dāng)try塊拋出一個異常時(shí),執(zhí)行代碼將跳到catch塊去,并從第一個catch塊開始匹配,直到找到符合的catch塊。請看下面的代碼說明: view plaincopy to clipboardprint? 01.class MyException1 extends Exception { 02.} 03.class MyException2 extends Exception { 04.} 05.class MyException3 extends Exception { 06.} 07.class A { 08. public void proc() throws Exception{ 09. try{ 10. // 僅僅為了演示用 11. Random random = new Random(); 12. int i = random.nextInt(3); 13. if (i == 0) 14. throw new MyException1(); 15. else if (i == 1) 16. throw new MyException2(); 17. else if (i == 2) 18. throw new MyException3(); 19. } 20. catch(MyException1 e){ 21. // 當(dāng)拋出MyException1時(shí)會跳到這里來。 22. e.printStackTrace(); 23. } 24. catch(MyException2 e){ 25. // 當(dāng)拋出MyException2時(shí)會跳到這里來。 26. e.printStackTrace(); 27. } 28. catch (Exception e) { 29. // 當(dāng)拋出MyException3時(shí),由于上面沒有匹配的處理器, 30. // 并且Exception是MyException3的基類,所以會跳到這里來。 31. e.printStackTrace(); 32. // 可以重新拋出異常,系統(tǒng)將尋找更外層的異常處理器 33. throw e; 34. } 35. } 36.} 37. 38.public class Main { 39. public static void main(String[] args) { 40. A a = new A(); 41. try { 42. a.proc(); 43. } catch (Exception e) { 44. e.printStackTrace(); 45. } 46. } 47.} class MyException1 extends Exception { } class MyException2 extends Exception { } class MyException3 extends Exception { } class A { public void proc() throws Exception{ try{ // 僅僅為了演示用 Random random = new Random(); int i = random.nextInt(3); if (i == 0) throw new MyException1(); else if (i == 1) throw new MyException2(); else if (i == 2) throw new MyException3(); } catch(MyException1 e){ // 當(dāng)拋出MyException1時(shí)會跳到這里來。 e.printStackTrace(); } catch(MyException2 e){ // 當(dāng)拋出MyException2時(shí)會跳到這里來。 e.printStackTrace(); } catch (Exception e) { // 當(dāng)拋出MyException3時(shí),由于上面沒有匹配的處理器, // 并且Exception是MyException3的基類,所以會跳到這里來。 e.printStackTrace(); // 可以重新拋出異常,系統(tǒng)將尋找更外層的異常處理器 throw e; } } } public class Main { public static void main(String[] args) { A a = new A(); try { a.proc(); } catch (Exception e) { e.printStackTrace(); } } } •在異常處理器后面加上finally子句,無論異常是否發(fā)生,finally子句一定會被調(diào)用到,finally子句常被用于清理垃圾回收之外的資源,比如打開的文件,網(wǎng)絡(luò)鏈接等: view plaincopy to clipboardprint? 01.class MyException1 extends Exception { 02.} 03. 04.class A { 05. public void proc(){ 06. try{ 07. throw new MyException1(); 08. } 09. catch(MyException1 e){ 10. e.printStackTrace(); 11. } 12. finally { 13. System.out.println("Hello"); 14. } 15. } 16.} 17. 18.public class Main { 19. public static void main(String[] args) { 20. A a = new A(); 21. a.proc(); 22. } 23.} 24.最后的輸出是: 25.MyException1 26. at A.proc(Main.java:12) 27. at Main.main(Main.java:27) 28.Hello class MyException1 extends Exception { } class A { public void proc(){ try{ throw new MyException1(); } catch(MyException1 e){ e.printStackTrace(); } finally { System.out.println("Hello"); } } } public class Main { public static void main(String[] args) { A a = new A(); a.proc(); } } 最后的輸出是: MyException1 at A.proc(Main.java:12) at Main.main(Main.java:27) Hello 3. 異常的限制:對于繼承類,它如果所覆蓋的方法有異常說明,則所列出的異常類,必須是基類該方法所列出的異常類的子集,先看一個例子:view plaincopy to clipboardprint? 01.class MyException1 extends Exception { 02.} 03.class A { 04. public void proc(){ 05. } 06.} 07.class B extends A { 08. // 編譯錯誤:因?yàn)锳.proc沒有異常說明,所以子類也不能有異常說明 09. // 解決的方法是為A.proc加上異常說明:throws MyException1 10. // 或者在throw new MyException1();加上try塊并去掉異常說明 11. public void proc() throws MyException1 { 12. throw new MyException1(); 13. } 14.} class MyException1 extends Exception { } class A { public void proc(){ } } class B extends A { // 編譯錯誤:因?yàn)锳.proc沒有異常說明,所以子類也不能有異常說明 // 解決的方法是為A.proc加上異常說明:throws MyException1 // 或者在throw new MyException1();加上try塊并去掉異常說明 public void proc() throws MyException1 { throw new MyException1(); } } 再看一下例子:view plaincopy to clipboardprint? 01.class MyException1 extends Exception { 02.} 03.class MyException2 extends Exception { 04.} 05.class A { 06. public void proc() throws MyException1 { 07. } 08.} 09.class B extends A { 10. // 錯誤:因?yàn)锳.proc只聲明了MyException1異常 11. public void proc() throws MyException2 { 12. } 13.} class MyException1 extends Exception { } class MyException2 extends Exception { } class A { public void proc() throws MyException1 { } } class B extends A { // 錯誤:因?yàn)锳.proc只聲明了MyException1異常 public void proc() throws MyException2 { } } 構(gòu)造器是一個例外,繼承類可以聲明更多的異常類,但必須加上基類所聲明的異常類:view plaincopy to clipboardprint? 01.class MyException1 extends Exception { 02.} 03.class MyException2 extends Exception { 04.} 05.class A { 06. A() throws MyException1 { 07. 08. } 09. public void proc() throws MyException1 { 10. } 11.} 12.class B extends A { 13. B() throws MyException1, MyException2 { 14. } 15.} class MyException1 extends Exception { } class MyException2 extends Exception { } class A { A() throws MyException1 { } public void proc() throws MyException1 { } } class B extends A { B() throws MyException1, MyException2 { } } |