Java - 异常
相關文檔:https://www.nowcoder.com/questionTerminal/a4a96e226c7b4dafae8250db4ff88af5?toCommentId=17805?
異常的分類:
解釋:
?所有異常類型都是?Throwable 類的子類,它包含Exception類和Error類;Exception又包括checked exception(已檢查異常)和unchecked exception(未檢查異常);
?Error、RuntimeException及其子類被稱為 未檢查異常,其它的被稱為 已檢查異常;
?未檢查異常也叫作運行時異常,已檢查異常也叫作編譯時異常;
?unchecked exception:Java編譯器不要求對未檢查異常一定捕獲或拋出,可以不做處理;此類異常通常是在邏輯上有錯誤,可以通過修改代碼避免;
?checked exception:Java編譯器要求對檢查異常必須捕獲或拋出;代碼邏輯沒有錯誤,但程序運行時會因為IO等錯誤導致異常,你在編寫程序階段是預料不到的;如果不處理這些異常,程序將來肯定會出錯;所以編譯器會提示你要去捕獲并處理這種可能發生的異常,不處理就不能通過編譯;
?未檢查異常不需要我們程序員關心(Error是我們解決不了的;RuntimeException在程序中到處都是,由程序員水平造成的,水平高這種異常就少);我們只需要可以關心對已檢查異常的處理;
已檢查異常舉例:
未檢查異常舉例:
?NullPointerException - 空指針引用異常
?ClassCastException - 類型強制轉換異常。
?IllegalArgumentException - 傳遞非法參數異常。
?ArithmeticException - 算術運算異常
?ArrayStoreException - 向數組中存放與聲明類型不兼容對象異常
?IndexOutOfBoundsException - 下標越界異常
?NegativeArraySizeException - 創建一個大小為負數的數組錯誤異常
?NumberFormatException - 數字格式異常
?SecurityException - 安全異常
?UnsupportedOperationException - 不支持的操作異常
?FileNotFoundException - 文件未找到異常
對已檢查異常進行處理的方式:繼續拋出(throws)、捕獲(try-catch-finally);
對未檢查異常進行處理的方式:繼續拋出、捕獲、不處理;
Java異常處理機制(throws的實現機制):層層上拋,如果異常沒法處理,就會拋給本方法的調用者,一直往上拋,直到被處理;(沒被處理)或者最終拋給main函數調用者(JVM),程序停止,打印異常棧信息;
五個關鍵字:
?try:試一試,把可能產生異常的代碼包住;
?catch:捕獲異常,針對兩種拋出異常進行捕獲:
? 第一種:JVM產生一個異常對象并拋出,希望得到處理;
? 第二種:通過 throw new **Exception(); 由程序員自己拋出的異常;
?finally:在以下三種情況中都會執行,用于釋放資源,肯定會執行:
? 無異常:try全部 + finally + 正常結尾;
? 有異常被catch:try開始到出現異常的地方 + 某個catch + finally + 正常結尾;
? 有異常沒被catch住:try開始到出現異常的地方 + finally + 停止;
?throw:在方法內部使用,用于主動拋出異常;
?throws:聲明本方法可能會拋出異常,希望調用者小心;
? 如果是uncheckedException,(RuntimeException及其子類)調用者可以處理也可以不處理;
? 如果是checkedException,調用者必須處理;(如何處理:加try-catch;給所在的方法加上throws說明,將異常拋到調用棧的上一層);
一個try可以有多個catch,如果是并列關系,誰上誰下均可;如果有包含關系:先小后大(異常類型的書寫順序必須是子類在前,父類在后);
聲明已檢查異常:
?在遇到以下4中情況時,應該拋出異常:
? 1.調用一個拋出已檢查異常的方法;
? 2.程序運行過程中發現錯誤,并且利用 throw 語句拋出一個已檢查異常;
? 3.程序出現錯誤,會拋出未檢查異常時;
? 4.Java虛擬機和運行時庫出現的內部錯誤;
?不要聲明Java的內部錯誤(從 Error 繼承的錯誤);因為任何程序代碼都可能會拋出這種錯誤,而我們對其沒有任何控制能力;
?也不要聲明未檢查異常(從 RuntimeException 那繼承的異常),這些異常完全在我們控制之內,是因為我們編寫程序時出現的錯誤代碼,對于這種異常我們應該致力于修改、完善我們的代碼;
?一個方法必須聲明所有可能拋出的已檢查異常;而未檢查異常要么不可控制(Error),要么就應該避免(RuntimeException);如果方法沒有聲明所有可能發生的已檢查異常,編譯器就會給出一個錯誤信息;
?如果子類覆蓋了父類中的一個方法,則子類中該方法聲明的已檢查異常不能比超類方法中聲明的已檢查異常更通用(子類方法中可以拋出更特定的異常,或者根本不拋出任何異常);如果超類方法沒有拋出任何已檢查異常,子類也不能拋出任何已檢查異常;
?如果類中一個方法聲明將會拋出一個異常,而這個異常是某個特定類的實例時,則這個方法就有可能拋出一個這個類的異常,或者這個類的任意一個子類的異常;
如何拋出一個已經存在的異常類:
?方法1:
? throw new EOFException();
?方法2:
? EOFException e = new EOFException();
? throw e;
如何拋出一個未存在的異常類(自定義異常):
?1.定義一個派生于Exception的類,或者派生于Exception子類的類;注意:定義的類應該包含兩個構造器,一個是默認的構造器,一個是帶有詳細描述信息的構造器(超類的Throwable的toString方法將會打印出這些詳細信息,這在調試中非常有用);
?2.此時就可以實現拋出一個已經存在的異常類;
捕獲異常:
?如果調用一個拋出已檢查異常的方法,就必須對它進行處理,或者將它繼續進行傳遞;
?通常,應該捕獲那些知道如何處理的異常,而將那些不知道怎么處理的異常繼續進行傳遞;
?如果編寫一個覆蓋超類的方法,而這個方法又沒有拋出異常,那么這個方法就必須捕獲方法代碼中出現的每一個已檢查異常;不允許在子類的throw說明符中出現超過超類方法所列出的異常類型范圍;
?在catch子句中可以拋出一個異常,這樣做的目的是改變異常的類型;有一種更好的處理方法(包裝技術),可以將原始異常設置為新異常的“原因”:
? catch(SQLException e)
? {
? ?Throwable se = new ServletException(“database error”);
? ?se.initCause(e);
? ?throw se;
? }
? 當捕獲到異常時,就可以通過 Throwable e = se.getCause(); 重新得到原始異常信息;
? 如果在代碼中發生了一個已檢查異常,而不允許拋出它,那么我們就可以使用包裝技術;我們可以捕獲這個已檢查異常,并將它包裝成一個運行時異常;
finally 子句:
?推薦獨立使用try/catch 和 try/finally 語句塊:
? try
? {
? ? try
? ?{
? ?}
? ?finally
? ?{
? ? ?// 只有一個職責:就是確保關閉資源
? ?}
? }
? catch
? {
? ? // 只有一個職責:就是確保報告出現的錯誤
? }
?try 語句塊中如果有 return 語句,在返回之前,finally 子句中的內容將會被執行;如果 finally 中也有 return 語句,finally中的return語句返回值會覆蓋try塊中return語句的返回值;
?finally中拋出異常的更好的解決方法:使用帶資源的try語句:
? 前提是這個資源是屬于一個實現了AutoCloseable接口(或是其子接口:Closeable)的類;
? 不論這個帶資源的語句塊如何退出(正常退出或拋出異常),都會將資源進行關閉,原來的異常會重新拋出;
? 使用帶資源的try語句,其本身還可以有catch子句和一個finally子句,這些子句會在關閉資源后執行,但不建議加;
使用異常機制的技巧:
1.異常處理不能代替簡單的測試:
?因為捕獲異常的時間大大超過簡單測試的時間;
?使用異常的基本規則:只在異常情況下使用異常機制;
2.不要過分地細化異常:
?不要將每一條語句分裝在一個獨立的try語句塊中,應該講整個任務包裝在一個try語句塊中;
3.利用異常層次結構:
?不要只拋出RuntimeException異常;應該尋找更加適當的子類或創建自己的異常類;
?不要只捕獲Throwable異常,否則會使程序代碼更難讀,更難維護;
?考慮已檢查異常與未檢查異常的區別;不要因為邏輯錯誤拋出已檢查異常;
?將一種異常轉換成另一種更加適合的異常時不要猶豫;
4.不要壓制異常:
?不太理解,應該是:只要可能拋出異常的地方,就進行捕獲;
5.在檢測錯誤時,“苛刻”要比放任更好:
?在檢測錯誤時,不要擔心拋出異常;
6.不要羞于傳遞異常:
?并不是要捕獲拋出的全部異常,在適合的場景應該講異常往外拋而不是捕獲;
5和6可以歸納為:“早拋出,晚捕獲”;
處理異常經驗:
1、處理運行時異常時,通過邏輯去合理規避同時輔助try-catch處理;
2、在多重catch塊后面,可以加一個catch(Exception)來處理可能會被遺漏的異常;
3、對于不確定的代碼,也可以加上try-catch,處理潛在的異常;
4、盡量去處理異常,切忌只是簡單的調用printStackTrace()去打印輸出;
5、具體如何處理異常,要根據不同的業務需求和異常類型去決定;
6、盡量添加finally語句塊去釋放占用的資源;
轉載于:https://www.cnblogs.com/kehuaihan/p/8460414.html
總結
- 上一篇: 购物网站
- 下一篇: ngDialog 点击窗口以外不允许关闭