目錄
- 一、異常
- 1.1 什么是異常
- 1.2 異常機制的作用
- 1.3 常見的異常
- 2.3 異常的分類
- 1. Error
- 2. Exception
- ① 運行時異常
- ② 編譯期異常
- 總結:
- 二、異常的處理
- 2.1 拋出異常
- 3.1 拋出異常語法
- 3.2 試圖捕獲異常
- 3.3 捕獲異常與拋出異常的區別
- 1. 拋出異常
- 2.捕獲異常
- 三、finally
- 四、throw 異常的產生(創建)
- 四、異常類的API
- 五、自定義異常
- 最后
一、異常
1.1 什么是異常
- 異常(exception),就是程序中出現的錯誤
- 就好比你在工作的時候,突然家里出了點情況,中斷了你工作,這就是出現了異常情況。
1.2 異常機制的作用
- 通過打印出的異常信息,我們可以知道是哪里的代碼出現了問題,并大概了解為什么會出現這個問題,方便我們去解決問題
1.3 常見的異常
-
算術異常 ArithmeticException
-
數組下標越界異常 ArrayIndexOutOfBoundsException
-
空指針異常 NullPointerException
-
類轉換異常ClassCastException
-
解析異常 ParseException
-
堆棧內存溢出錯誤 StackOverflowError
2.3 異常的分類
- 異常也是一種類,Throwable 類是 Java 語言中所有錯誤或異常的超類。
1. Error
- Error 是 Throwable 的子類,用于指示合理的應用程序不應該試圖捕獲的嚴重問題。
- 也就是Error一般都是嚴重問題,遇到必須里面立馬解決,所以不應該捕獲…
- 例如:堆棧內存溢出錯誤 StackOverflowError
2. Exception
可以拋出,也可以捕獲的異常
Exception子類:RuntimeException(運行時異常)和其他異常類
① 運行時異常
- 這些異常在編譯時不強制要求處理,通常是由程序中的錯誤引起的,例如 NullPointerException、ArrayIndexOutOfBoundsException 等,這類異常可以選擇處理,但并非強制要求。
- 這些類是: RuntimeException及其子類的都是運行時異常
② 編譯期異常
- 編譯期異常是用戶錯誤或問題引起的異常,這些異常在編譯時強制要求程序員處理。例如要打開一個不存在文件時,一個異常就發生了,這些異常在編譯時不能被簡單地忽略。
總結:
二、異常的處理
我們知道異常的基本概念了,那異常如何處理呢?
-
異常的處理只有兩種方式
- 拋出異常
- 捕獲異常
2.1 拋出異常
-
什么是拋出異常?
目前為止任何異常,默認的處理方式都是拋出
所謂拋出異常就是直接將錯誤信息打印到控制臺
3.1 拋出異常語法
- 前面講到運行時異常,可以不用處理,通過上圖也發現系統會默認自動拋出
- 如果是編譯期異常,想要拋出異常,語法是
- 位置: 在方法參數列表后,{}前
- 寫:throws 異常類名,類名2,…
public static void main(String[] args) throws ArithmeticException,ArrayIndexOutOfBoundsException {}
- 聲明拋出異常后,什么效果?
- 如果代碼一切正常,雖然聲明的有拋出異常,也不會在控制臺打印異常信息
- 如果代碼真的有異常,聲明了拋出異常,
- 1錯誤信息就會在控制臺打印
- 2拋出異常后,后續代碼不再執行
// 以下代碼中19行報錯,4,5,6,7.7都不再執行public static void main(String[] args) {System.out.println(0.0 );m1();System.out.println(7.7 );}public static void m1() {System.out.println(1);System.out.println(2);m2();System.out.println(5);System.out.println(6);}public static void m2(){System.out.println(3);System.out.println(4 / 0);System.out.println(4 );}
- 但是如果方法拋出的是編譯期異常,誰調用這個拋出編譯期異常的方法,那么哪個方法就得處理!!
- 特殊的 ,關于拋出異常在重寫方法時也有要求…
- 子類的重寫后,方法拋出的異常范圍要 <= 父類的異常范圍
- 特殊的,如果父類方法沒有拋出異常,那么子類方法內有異常也不能拋出,只能捕獲
總結拋出異常
- 哪里拋出的?
- 方法簽名上只是聲明可能拋出的異常類型
- 方法體內,執行到某一行代碼,如果有錯才會拋出
- 拋給誰?
- 如果有異常拋出,誰調用拋給哪個方法
- 最終拋出到main
- main方法拋出到jvm,jvm打印到控制臺
- 拋到哪?
- 拋出到控制臺
- 拋出了啥?
- 異常的線程信息
- 異常類型
- 異常原因
- 異常位置
3.2 試圖捕獲異常
試圖捕獲(try-catch)
- 語法
try{// 可能會有報錯的代碼
} catch (異常類名 對象名){// 如果抓到異常,執行這里
}
執行流程:
- 代碼正常運行,執行try后
- 進入try執行,如果try內一切正常,catch就跳過不執行
- 如果try內有異常
- try內異常處后續不執行
- catch捕獲到異常后,就會執行
- 無論try內有無異常,try-catch后的代碼都能運行
public static void main(String[] args) {System.out.println(1);System.out.println(2);try {System.out.println(3);System.out.println(4.1);System.out.println(4/0);System.out.println(4.2);}catch (ArithmeticException ae){System.out.println("捕獲到了異常:"+ae );}System.out.println(5);}
- 特殊情況1: 出現的異常和捕獲的異常不一致,try-catch失效
- 特殊情況2: 允許同時聲明catch多個異常
- 特殊情況3: 如果真需要catch寫多個異常,用于去捕獲多種異常的話,建議這么寫,寫一個Exception,直接捕獲最大類異常,這樣所有異常子類都可以捕獲
3.3 捕獲異常與拋出異常的區別
1. 拋出異常
通過上圖發現程序中斷,后續代碼無法執行
2.捕獲異常
通過上圖發現,當try代碼塊中出現異常后,catch代碼塊捕獲到異常,執行catch中的語句,而且try-catch外面的語句正常執行
三、finally
- finally配合try-catch使用
- 作用: 最終一定會執行,即放在finally里面的代碼,之前無論有無報錯,無論是拋出還是捕獲,fianlly里面的代碼最終一定能執行
語法:
try{// ...
}catch(Exception e){}finally{}
或者
try{// ...
}finally{}
finally一般用在 關閉流/通道的場景中,用于及時釋放資源
例如: IO流,jdbc連接
四、throw 異常的產生(創建)
- 之前說的是拋出異常,捕獲異常都是異常出現了之后的解決方案.
如何制造產生異常呢?
產生異常,兩個步驟:
- 創建異常對象
- 通過throw 拋出異常對象
- 需要注意,throw拋出的是編譯期異常,需要強制處理
- throw拋出的是運行時異常,可以默認不用處理
public class Demo5 {public static void main(String[] args) throws ParseException {String s = parseBirthday2("41011120240101123");System.out.println(s );}/**需求: 解析身份證號中的生日,要求身份證號長度18位,否則拋出異常*/public static String parseBirthday(String idNumber) throws ParseException{if (idNumber.length() == 18) {return idNumber.substring(6,14);}// 拋出異常(編譯期異常,需要處理)throw new ParseException("生日解析出錯,格式不正確",1);}public static String parseBirthday2(String idNumber) {if (idNumber.length() == 18) {return idNumber.substring(6,14);}// 拋出異常(運行時異常,不用管)throw new RuntimeException("2222生日解析出錯,格式不正確");}
}
- 總結throw和throws…
throw | throws | |
---|---|---|
位置 | 方法體內 | 方法簽名上 |
后面寫什么 | 跟1個異常對象 | 跟異常類名,且允許多個 |
作用 | 一定會拋出異常的 | 聲明拋出的異常類型,但是不一定有異常 |
四、異常類的API
查閱API,發現所有異常,方法基本上都直接繼承自Throwable類,常用的方法
- 構造方法 Throwable(String message)
- 所有的異常對象,都通過有參構造將異常信息傳遞給Throwable父類
- 且這個message就是異常信息
- String getMessage()
- void printStackTrace()
- String toString()
public class Demo6 {public static void main(String[] args) {try {System.out.println(1/0 );}catch (ArithmeticException ae) {// String message = ae.getMessage( );// System.out.println("message = " + message);//// String string = ae.toString( );// System.out.println("string = " + string);// 獲得這些異常信息,將來將其輸出到本地磁盤日志文件ae.printStackTrace();}}
}
五、自定義異常
自定義異常實現步驟
- 創建一個異常類,命名規范XxxxException
- 繼承一個合適的父類
- 繼承編譯期異常
- 繼承運行時異常
- 設計一個有參構造,將異常信息參數通過super傳遞給父類異常
如何使用自定義異常類:
- 在需要使用的方法內部,通過throw+該異常對象,將其拋出
// 異常類
public class AgeOutOfBoundsException extends Exception{public AgeOutOfBoundsException(String msg){super(msg);}}
// 使用異常
public class Dog {private int age;public int getAge() {return age;}public void setAge(int age) throws Exception{if (age <= 0 || age >= 100) {throw new AgeOutOfBoundsException("年齡"+age+"越界!");}this.age = age;}
}
最后
如果感覺有收獲的話,點個贊 👍🏻 吧。
??????本人菜鳥修行期,如有錯誤,歡迎各位大佬評論批評指正!😄😄😄
💘💘💘如果覺得這篇文對你有幫助的話,也請給個點贊、收藏下吧,非常感謝!👍 👍 👍