1、拋出異常之後
1).使用new在對象上建立異常對象
2).終止當前的執行路徑
3).從當前環境中彈出對異常對象的引用
4).異常處理機制接管程式,並開始執行異常處理機制
2、異常處理理論上有兩種基本模型
1).終止模型:一旦異常拋出,就表明錯誤無法挽回,也能回來繼續執行。比較實用。
2).恢複模型:異常處理之後繼續執行程式。但是可能導致“耦合”。
3、自定異常類(具有帶參數的構造器)
class SimpleException extends Exception{ public SimpleException(){} public SimpleException(String msg){ super(msg); }}public class SimpleExceptionDemo{ public void func() throws SimpleException{ System.out.println("Throw SimpleExceptionfrom func()."); throw new SimpleException(); } public void func1() throws SimpleException{ System.out.println("ThrowSimpleException from func1()."); throw new SimpleException("Originated in func1()"); } public static void main(String[] args){ SimpleExceptionDemo sed = new SimpleExceptionDemo(); try { sed.func(); } catch (SimpleException e) { e.printStackTrace(); } try { sed.func1(); } catch (SimpleException e) { e.printStackTrace(); } }}
運行結果:
4、異常說明:實用關鍵字throws,告知用戶端程式員可能會拋出的異常類型。
5、在定義抽象基類和介面時,可以throws一些實際上並不拋出的異常。這樣做的好處:為異常先佔個位子,以後就可以拋出這種異常而不用修改已有的代碼。
6、捕獲所有異常(最好放在處理常式列表的末位):
catch (Exception e) { System.err.println("Caught an exception");}
7、如果當前異常對象重新拋出,那麼printStackTrace()方法顯示的將是原來異常拋出點的調用棧資訊,而非重新拋出點的資訊。要想更新這個資訊,可以調用fillInStackTrace()方法,這將返回一個Throwable對象,它是通過把當前調用棧資訊填入原來那個異常對象而建立的。
8、
public static void main(String[] args) throws Throwable{ try{ throw new Throwable(); }catch(Exception e){ System.err.println("Caught inmain()"); } }
因為Throwable是Exception的基類,所以下面程式中將不能再main()裡捕獲。
9、RuntimeException(或任何從它繼承的異常)是一個特例,對於這種異常,編譯器不需要異常說明。原因:
1).無法預料的錯誤。比如在你控制範圍之外傳遞進來的null引用。
2).作為程式員,應該在代碼中進行檢查的錯誤。(比如對於ArrayIndexOutOfBoundsException,就得注意一下數組的大小了。)在一個地方發生的異常,常常會在另一個地方導致錯誤。
10、finally的作用:把除了記憶體之外的資源恢複到它們的初始狀態。例如:已經開啟的檔案盒網路連接,在螢幕上畫的圖形,甚至可以是外部世界的某個開關。
11、異常丟失:
class FirstException extends Exception{ public String toString(){ return "The firstException."; }}class SecondException extends Exception{ public String toString(){ return "The secondException."; }} public class ErrorFinally{ void firstFunc() throws FirstException{ throw new FirstException(); } void secondFunc() throws SecondException{ throw new SecondException(); } public static void main(String[] args) throws Exception{ ErrorFinally error = new ErrorFinally(); try { error.firstFunc(); } finally{ error.secondFunc(); } }}
運行結果:
可以看到,FirstException不見了,它被finally裡的SecondException取代了。
12、異常的限制:當覆蓋方法的時候,只能拋出在基類方法的異常說明裡列出的那些異常。這個限制很有用,因為這意味著,當基類使用的代碼應用到其衍生類別對象的時候,一樣能夠工作(當然,這是物件導向的基本概念),異常也不例外。
1).衍生類別建構函式的異常說明必須包含基類構造器的異常說明。
2).衍生類別構造器不能捕獲基類構造器拋出的異常。(P275第三段最後一句怎麼理解??)
3).衍生類別的方法可以不拋出異常,即使基類的方法有拋出異常。
4).衍生類別的方法可以拋出繼承自"基類方法所拋出異常"的異常。
請看下面例子:
class BaseException extends Exception{}class FuncException extends Exception{}class OtherfuncException extends FuncException{}class Base { Base() throws BaseException { } void func() throws FuncException { System.out.println("Base.func()"); } void otherFunc() throws FuncException { System.out.println("Base.otherFunc()"); }}public class InheritBase extends Base{ //衍生類別建構函式的異常說明必須包含基類構造器的異常說明 public InheritBase() throws BaseException { super(); } //衍生類別的方法可以不拋出異常,即使基類的方法有拋出異常。 void func(){ System.out.println("InheritBase.func"); } //衍生類別的方法可以拋出繼承自"基類方法所拋出異常"的異常,如下OtherfuncException繼承自FuncException //因為例外處理常式能捕獲FuncException就一定能捕獲OtherfuncException。 void otherFunc() throws OtherfuncException{ System.out.println("InheritBase.otherFunc()"); } public static void main(String[] args){ try { Base ib = new InheritBase(); ib.func(); } catch (BaseException e) { System.err.println("Caught BaseException."); } catch (FuncException e) { System.err.println("Caught funcException."); } }}
13、把異常傳給控制台
public static void main(String[] args) throws Exception{ }
14、把“被檢查的異常”轉換為“不檢查的異常”:把“被檢查的異常”這種功能給屏蔽掉。
1).
try { } catch (BeCheckedException e) { throw new RuntimeException(e);}
這樣做的好處:不用“吐下”異常(“吐下”後異常完全消失),也不必把它放到方法的異常說明裡(throws),而異常鏈還能保證你不會丟失任何原始異常的資訊。
2).你也可以不寫try-catch字句和/或異常說明,直接忽略異常,讓它沿著調用棧往上“冒泡”。同時,還可以用getCause()捕獲並處理特定的異常,如下例子:
class ZeroException extends Exception{}class FirstException extends Exception{}class secondException extends Exception{}class SomeOtherException extends Exception{}//把”被檢查的異常“封裝起來class WrapCheckException{ void throwRuntimeException(int type){ try{ switch(type){ case 0: throw new ZeroException(); case 1: throw new FirstException(); case 2: throw new secondException(); default: return; } }catch(Exception e){ throw new RuntimeException(e); } }}public class TurnOffChecking{ public static void main(String[] args){ WrapCheckException wce = new WrapCheckException(); wce.throwRuntimeException(3); for(int i = 0; i < 4; i++){ try{ if(i < 3) wce.throwRuntimeException(i); else throw new SomeOtherException(); }catch(SomeOtherException e){ System.out.println("SomeOtherException:" + e); }catch(RuntimeException e){ try { //用getCause捕獲特定異常 throw e.getCause(); } catch (ZeroException e1) { System.out.println("ZeroException:" + e1); } catch (FirstException e1) { System.out.println("FirstException:" + e1); } catch (secondException e1) { System.out.println("secondException:" + e1); } catch (Throwable e1) { System.out.println("Throwable:" + e1); } } } }}
運行結果:
1).WrapCheckException. throwRuntimeException()把不同的異常封裝進了RuntimeException對象。
2).可以不用try塊就可以調用throwRuntimeException(),但是,也可以使用try塊捕獲你想捕獲的異常。
3).程式中把getCause()的結果(也就是被封裝的那個原始異常)拋出來,然後用它們自己的catch子句進行處理。
以上內容整理自《Java編程思想》,若有遺漏,請您不吝指出。
覺得自己進度有點慢,多麼想一口氣把這本書看完。我還有幾本?17天。現在才267頁。我得加速!!