Java 語言-7 Java 基礎語法 3.0
7.1 異常機制
7.1.1 認識異常
-
異常(exception)又稱例外、差錯、違例
- 對應 Java 執行錯誤處理機制
-
簡單分類
- 檢查性異常:這是程式設計師不可預知的異常,最具代表性的檢查性錯誤是使用者錯誤或問題引起的異常,這些異常在編譯時不能被簡單的忽略
- 執行時異常:這是程式設計師可以避免的異常
- 錯誤(Error):錯誤並不是異常,而脫離程式設計師控制的問題。在程式碼中通常被忽略
-
傳統語言(例如:C 語言)處理異常
- 方式:
- if 語句判斷是否出現異常
- 全程使用變數 ErroNo 記錄異常
- 缺點:
- 可讀性差。正常處理與異常處理的程式碼進行同樣的處理
- 可維護性差。每次呼叫一個方法時都進行錯誤檢查
- 職責不清。錯誤由誰處理分辨不清
- 方式:
-
Java 的異常處理
- 丟擲(throw)異常
- 執行時系統在呼叫棧中查詢
- 從生成異常的方法開始回溯,直到找到;
- 捕獲(catch)異常程式碼
-
Java 異常體系結構
- Java 將異常當作物件處理,定義了一個基類 java.lang.Throwable 作為所有異常的超類
- 在 Java API 中將定義的許多異常類通常分為兩大類,錯誤(Error)和異常(Exception),一般說的異常是指 Exception 及其子類
-
Error & Exception
- Error 類物件由 Java 虛擬機器(JVM)生成並丟擲,大多數錯誤與程式碼編寫者所執行的操作無關
- 大多數時 Java 虛擬機器執行錯誤(Virtual MachineError),還有虛擬機器企圖執行應用時
- 這些錯誤是不可查的,因為這些錯誤是在應用程式的控制和處理之外,而且絕大數是程式執行時不允許出現的狀況
- Exception
- 在 Exception 中有一個重要的子類 RuntimeException(執行時異常),這些異常一般是由程式邏輯錯誤引起。程式應該從邏輯角度儘可能避免這類異常的發生
- 二者區別:
- Error 通常是災難級的致命錯誤,是程式無法控制和處理的當出現這些異常,Java 虛擬機器一般會選擇終止執行緒
- Exception 通常情況下可以被程式處理,並且在程式中應該儘可能的去處理這些異常
- Error 類物件由 Java 虛擬機器(JVM)生成並丟擲,大多數錯誤與程式碼編寫者所執行的操作無關
-
Exception 類
-
構造方法的三種形式:
public Exception(); public Exception(String message); public Exception(String message,Throwable cause);
-
常見讀取方式:
- getMessage():獲取異常資訊
- getCause():獲取內部原因
- printStackTrace():輸出呼叫棧的跟蹤資訊,即 IDEA 輸出的異常資訊
-
7.1.2 處理異常
-
處理異常的五個關鍵字
-
try、catch、finally、throw、throws
try-catch:捕獲異常。try:監控區域;catch:捕獲異常。
finally:處理善後工作。無論是否經過 try-catch 都會執行 finally 語句。多用於 IO 的資源關閉
throw 和 throws:丟擲異常物件。throw 在方法中使用;throws 在宣告方法時使用
-
-
基本寫法:
try-catch
try{ …… }catch(Exception e){ …… }finally{ …… }
catch 語句可以有 0 到多個
finally 語句可以有 0 到 1 個
- 多異常的處理:子類異常要排在父類異常前
-
快捷鍵(IDEA):
Crtl+Alt+T
-
主動丟擲異常:當已知程式碼有問題,用 throw 主動丟擲異常,主動結束程式碼
-
一般在方法中使用
-
例如:
public void test(int a;int b){ if (b==0){ throw new ArithmeticException(); } }
-
-
在方法上丟擲異常使用 throws
-
例如:
public void test(int a;int b) throws ArithmeticException{ if (b==0){ throw new ArithmeticException(); } }
-
-
重拋異常:其中對於異常,不僅需要進行捕獲處理,有時候還需要將異常進一步傳遞給呼叫者
-
方法:
- 將當前捕獲的異常再次丟擲,如:
throw e;
- 重新生成異常並丟擲,如:
throw new Exception("some message");
- 重新生成並丟擲一個新異常,該異常包含了當前異常的資訊,如:
throw new Exxception("some message",e);
- 這種方式可用 e.getCause() 來得到內部異常
- 將當前捕獲的異常再次丟擲,如:
7.1.3 自定義異常
-
用的不多,Java 自帶的異常就非常多了,而且還有很多開源的異常在網上,所有一般都不需要自定義異常
-
大體方法:自定義異常類只需要繼承 Exception 類即可
-
大體步驟:
- 建立自定義異常類
- 在方法體中通過 throw 關鍵字丟擲異常物件
- 如果在當前丟擲異常的方法中處理異常,可以使用 try-catch 捕獲異常並處理
- 如果不在當前方法中處理,則需要在方法的宣告處使用 throws 關鍵字指明需要丟擲給方法呼叫者的異常
- 在出現異常方法的呼叫者中捕獲處理異常
-
如果仍然不知道怎樣寫,可以檢視 Java 自帶的異常方法,作為案例
-
示例:定義一個輸入大於10的數就丟擲異常的自定義異常類
定義自定義異常類 MyException
package exercise.DivMyException; public class MyException extends Exception{ //傳遞數字>10 private int detail; public MyException(int a) { this.detail =a; } //toString:異常的列印資訊 @Override public String toString() { return "MyException{" + "detail=" + detail + '}'; } }
定義測試自定義異常類 Test
package exercise.DivMyException; import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput; public class Test { //可能存在異常的方法 static void test(int a) { System.out.println("傳遞引數為:"+a); if(a>10){ try { throw new MyException(a); } catch (MyException e) { System.out.println("MyException:"+e); } }else { System.out.println("OK"); } } public static void main(String[] args) { test(1); } }
測試結果:
傳遞引數為:1 OK
傳遞引數為:10 OK
傳遞引數為:11 MyException:MyException{detail=11}
-
實際經驗總結¥
- 處理執行時異常時,採用邏輯去合理規避同時採用 try-catch 輔助處理
- 在多重 catch 塊後面,可以加入 catch(Exception) 來處理可能會被遺漏的的異常
- 對於不確定的程式碼,也可以使用 try-catch 處理潛在的異常
- 在 IDEA 中潛藏的異常會以波浪線標紅,可以使用
alt+Enter
檢視提示資訊
- 在 IDEA 中潛藏的異常會以波浪線標紅,可以使用
- 處理異常時,儘量細緻的去處理異常,切忌只是簡單呼叫 printStackTrace() 去列印輸出
- 具體如何處理異常,需要根據不同的業務需求和異常型別去決定
- 處理過程中,儘量新增 finally 語句去釋放佔用的資源
- 特別是 IO、Scanner
7.2 類、介面等完整定義
-
如果看不懂個別意思,可能是因為沒學習到;如果基本都沒看懂,就是前面沒有學習紮實
-
完整類定義
//類宣告 [public][abstract | final] class className [extends superclassName][implements InterfaceName]{ //成員變數宣告,可為多個 [public | protected | private][static][final][transient][volatile] type variableName; //方法定義,可為多個 [public | protected | private][static][final | abstract][native][synchronized] returnType methodName ([paramList]) //方法實現,可為多個 [throws exceptionList]{ statements } }
-
完整介面定義
//介面宣告 [public] interface InterfaceName [extends superInterfaceList]{ //常量宣告,可為多個 type constantName = Value; //方法宣告,可為多個 returnType methodName([paramList]); }
未加入 jdk 8 以後新加的定義方法
-
三種方法固定的宣告方式
-
構造方法:
calssName([paramList]){ …… }
-
main() 方法:
public static void main(String[] args){ …… }
-
finalize() 方法:
protected void finalize() throws throwable{ …… }
幾乎不用的
-
-
完整 Java 原始檔
//指定檔案中類所在包 package packageName; //指定引入的類 import packageName.[className | *]; //屬性為 public 的類定義 public classDefinition //介面或者類的定義 interfaceDefinition and classDefinition
原始檔名字必須與屬性為 public 的類的類名一致