1. 程式人生 > >java程式設計思想 第十二章 通過異常處理錯誤

java程式設計思想 第十二章 通過異常處理錯誤

1.異常處理是java中唯一正式的錯誤報告機制,並且通過編譯器強制執行

2.異常情形:指阻止當前方法或作用域繼續執行的問題。能做的就是從當前的環境中跳出,把問題提交給上一級環境,這就是丟擲異常時所發生的事情。

3.丟擲異常的時候:

1. 同java中其他物件的建立一樣,將使用new在堆上建立異常物件
2. 當前的執行路徑被終止,並且從當前環境中彈出異常物件的引用。
之後異常處理機制接管程式,並開始尋找一個恰當的地方來繼續執行程式,這個恰當的地方就是異常處理程式(任務:將程式從錯誤狀態中恢復,以使程式能要麼換一種方式執行,要麼繼續執行下去;以關鍵字catch表示,只有匹配的catch子句才能得到執行)

4. 標準異常類都有兩個構造器

1. 預設構造器
2. 接受字串作為引數,以便能夠把相關資訊放入異常物件的構造器

5. throw能夠任意型別的Throwable物件,Throwable是異常型別的根類

6. 異常處理機制:可以把所有動作都放在try塊裡,然後只需在一個地方就可以捕獲所有異常。

7. 異常處理理論:

1. 終止模型——java支援,一旦異常被丟擲,就表明錯誤已經無法挽回,也不能回來繼續執行
2. 恢復模型
    1. 異常處理程式的工作就是修正錯誤,然後重新嘗試調用出問題的方法,並認為第二次能成功。
    2. 再遇見錯誤的時候就不能丟擲異常,而是呼叫方法來修正該錯誤。
    3. 或者,把try塊放在while迴圈裡,這樣就不斷的進入try塊,直到得到滿意的結果。

8. 建立自定義異常——必須從已有的異常類繼承,做好是選擇意思相近的異常類繼承

1. 建立新的異常型別最簡單的方法是讓編譯器為你產生預設構造器
2. 對異常來說,最重要的部分就是類名

9. Exception.printStackTrace():將列印“從方法呼叫處直到異常丟擲處”的方法呼叫序列,傳送到System.out;使用它來列印異常資訊

10. 異常與記錄日誌

1. 靜態的Logger.getLogger()方法建立一個String引數相關聯的Logger物件(通常與錯誤相關的包名和類名),這個Logger物件會將其輸出傳送到System.error
2. 向Logger寫入的最簡單方式是:直接呼叫與日誌記錄訊息的級別相關聯的方法,如:server()
3. 如果將java.io.StringWriter物件傳遞給PrintWriter的構建器,通過呼叫toString()方法,就可以將輸出抽取成為一個String

11. 異常說明:使用throws關鍵字,後面接一個所有潛在異常型別的列表

1. 可以宣告將丟擲異常,實際上卻不丟擲,這在定義抽象基類和介面的時候很重要,這樣派生類或者介面實現能夠丟擲這些預先宣告的異常
2. 兩種意思:
    1. 我的程式碼會產生這種異常,這由你來處理
    2. 我的程式碼忽略了這些異常,這由你來處理

12. 被檢查的異常:在編譯時被強制檢查的異常

13. fillInStackTrace():用於在Throwable物件的內部記錄棧幀的當前狀態,返回一個Throwable物件

14. 重新丟擲異常

1. 把異常拋給上一級環境中的異常處理程式,同一個try塊的後續catch子句將被忽略,高一級環境中捕獲次異常的處理程式可以從這個異常物件中得到所有資訊
2. 如果只是丟擲當前異常物件,printStackTrace()顯示的將是原來異常丟擲點的呼叫棧資訊;呼叫fillInStackTrace()方法可以更新這個資訊(呼叫fillInStackTrace()的那一行就成為了異常的新發生地)

15. 異常鏈:想要在捕獲一個異常後丟擲另一個異常,並且把原始異常的資訊儲存下來(P260)

16. Throwable物件可分為兩種型別:Error和Exception

17. RuntimeException異常——不受檢查異常,這種異常屬於錯誤,被自動捕獲,不用程式設計師處理;如果不被捕獲,那麼在程式退出前將呼叫異常的printStackTrace()

18. 當java中的異常不允許我們回到異常丟擲的地點時,那麼如何處理呢?

1. 把try塊放在迴圈裡,就確立了一個“程式繼續執行之前必須要達到”的條件
2. 加入一個static型別的計數器或者別的裝置,使迴圈在放棄以前嘗試一定的次數

19. finally子句

1. 它能使程式設計師保證:無論try塊裡發生什麼,記憶體總能得到釋放。
2. 當涉及到break和continue語句的時候,finally子句也會被執行

20. 異常丟失:前一個異常還沒處理就丟擲下一個異常

21. 派生類構造器不能捕獲基類構造器丟擲的異常;在繼承中重寫方法時候訪問許可權不能縮小,但是異常說明的介面恰恰相反,只能縮小

22. 構造器(P272)

1. 對於構造階段可能會丟擲異常,並且要求清理的類,最安全的使用方式是使用巢狀的try子句
2. 清理慣用法在構造器不丟擲異常的時候也該運用,基本規則:在建立需要清理的物件之後,立即進入一個try-finally語句塊
3. 對於每一個構造,都必須包含在其自己的try-finally語句塊中,並且每一個物件構造器必須都跟隨一個try-finally語句塊以確保清理

23. 異常匹配

1. 丟擲異常的時候,異常處理系統會按照程式碼的書寫順序找出“最近”的處理程式。找到匹配的處理程式後,就認為異常將得到處理,然後就不再繼續查詢
2. 派生類的物件也可以匹配其基類的處理程式

24. 其他可選方式

1. 異常處理的一個重要原則:只有在你知道如何處理的情況下才捕獲異常
2. ”被檢查異常”——強制你在可能還沒準備好處理錯誤的時候被迫加上catch子句,導致“吞食則有害”
    1. 給main()加上異常說明,通過把它傳遞到控制檯,就不必再main()裡寫try-catch子句了
    2. 把“被檢查的異常”轉換為“不檢查的異常”
        1. 大型專案中避免起初不知道如何處理“被檢查的異常”時使用
        2. 即把“被檢查的異常”包裝進RuntimeException裡面
            3. throw new RuntimeException(e);
        4. 當你需要對其中的異常進行處理的時候,可以通過getCause()捕獲並處理特定的異常
                try{
                    throw RuntimeException.getCause();
                }catch(){
                }

25. 異常使用指南:

 1. 在知道該如何處理的情況下才捕獲異常
 2. 解決問題並且重新呼叫產生異常的方法
 3. 進行少許修補,然後繞過異常發生的地方繼續執行
 4. 用別的資料進行計算,以代替方法預計會返回的值
 5. 把當前執行環境下能做的事情儘量做完,然後把相同的異常重拋給更高層
 6. 把當前執行環境下能做的事情儘量做完,然後把不同的異常重拋給更高層
 7. 終止程式
 8. 進行簡化
 9. 讓類庫和程式更安全

26“報告”功能是異常的精髓所在。java堅定的強調所有的錯誤都以異常形式報告的這一事實。