1)異常定義
異常是指在程序在執行過程中,JVM的非正常停止,Java中異常本身就是一個類,產生異常意味著創建並拋出了一個異常對象 ,JVM處理異常的方法就是終止程序。
2)異常體系
Exception:編譯期異常,進行編譯(寫代碼)java程序出現的問題
手搓
RuntimeException:運行期異常,java程序運行過程中出現的問題
JVM
2.Error異常處理
內存溢出錯誤,數組太大,只能修改
Error: OutOfMemoryError: Java heap space
int[] arr = new int[1024*10240000*10000000*10000000];
3.Exception異常處理(非常重要)
①throw:在指定的方法內部拋出指定異常
特點:假裝沒有發生
throw 必須在方法內部使用,new的對象必須是Exception或其子類對象throw的原則(拋出):把這個異常對象傳遞到調用者處,並結束當前方法的執行//2種RTE異常,JVM來處理,throw出去
1.NullPointerException
int[] arr = null;
int e = getElement(arr,0);
2.ArrayIndexOutOfBoundsException
int[] arr = new int[3];
int e = getElement(arr,3);
public static int getElement(int[] arr,int index){
if(arr == null)//合法性判斷
throw new ArrayIndexOutOfBoundsException("傳遞的數組的值是null");
if(index<0 || index>arr.length-1)//合法性判斷
throw new ArrayIndexOutOfBoundsException("傳遞的索引超出了數組的使用範圍");
int ele = arr[index];
return ele;
}
②throws:拋出異常給方法調用者
特點:一路向北
方法內的throw拋出了編譯時異常,沒有處理,就需要throws拋出讓調用者處理
throws必須在方法尾部聲明,聲明的只能是Exception及其子類throws的原則(拋出):當前方法不處理異常,只提醒該方法的調用者處理方法中throw拋多少,方法屁股throws拋多少(只拋父類就行)調用throws方法:
(1).continue throws 給方法調用者,直到jvm中止程序
(2).try catch
代碼演示:
//1.throw時出錯
public static void readFile(String fileName) {
if(!fileName.equals("c:\\a.txt"))
throw new FileNotFoundException("傳遞的文件路徑不是c:\\a.txt");
//throw這裡編譯期異常,裂開了需要throws
public static void readFile(String fileName) throws FileNotFoundException
//2.執行到main方法,readFile報錯,繼續拋出
public static void main(String[] args) {
readFile("c:\\a.tx");//裂開了
System.out.println("路徑沒有問題,讀取文件");
public static void main(String[] args)throws Exception
'經歷2次拋出,路徑沒有問題,讀取文件'
//可以只拋出最高的父類
FileNotFoundException extends IOException extends Exception
public static void readFile(String fileName) throws FileNotFoundException,IOException{
...
if(!fileName.endsWith(".txt"))
throw new IOException("文件的後綴名不對");
public static void readFile(String fileName) throws IOException
public static void readFile(String fileName) throws Exception
③try catch:自身含有解決異常的邏輯
特點:直面困難
throws處理的缺點,主函數拋出給JVM,程序停止,後續代碼無法執行,引入try
public static void main(String[] args)throws Exception {
readFile("d:\\a.txt");
System.out.println("後續代碼");//不會執行
使用格式:
try{
可能產生異常的代碼
}catch(異常類名 變量名){//用來接收try中拋出的異常對象
...異常處理方法
catch(異常類名 變量名){
try中可能拋幾個異常,用幾個catch接
try中有異常產生,立即執行對應catch處理,完畢後執行tc外的代碼,不會再執行try中的代碼如果try中無異常,就不會執行catch,會把try中的代碼執行完,再執行tc外的代碼
public static void main(String[] args) {
readFile("c:\\a.txt");
System.out.println("資源釋放");
}catch (FileNotFoundException e) {//子類要在上
System.out.println("catch - 文件路徑錯誤");
catch (IOException e) {
System.out.println("catch - 文件後綴錯誤");
System.out.println("後續代碼");
//拋出給try解決
public static void readFile(String fileName) throws IOException {
throw new IOException("文件的後綴名不對呀");
System.out.println("後綴沒有問題");
System.out.println("路徑沒有問題");
readFile("c:\\a.txt");//後續代碼依舊會執行
後綴沒有問題
路徑沒有問題
資源釋放
後續代碼
④finally:執行try裡拋出異常之後不執行的代碼
特點:給try擦屁股的媽媽
readFile("c:\\a.tx");
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.println("資源釋放");//必定會執行!!!
finally裡面不要寫return!!!
若finally有return語句,永遠返回finally中的結果
int a = getA();
System.out.println(a);
public static int getA(){
int a = 10;
return a;
}catch (Exception e){
System.out.println(e);
//一定會執行的代碼
a = 100;
4.捕獲多個異常
1. 一個try對應一個catch
int[] arr = {1,2,3};
System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
}catch (ArrayIndexOutOfBoundsException e){
List<Integer> list = List.of(1, 2, 3);
System.out.println(list.get(3));//IndexOutOfBoundsException: Index 3 out-of-bounds for length 3
}catch (IndexOutOfBoundsException e){
2. 一個try對應多個catch(處理完一個注釋掉,再處理另一個)
//System.out.println(arr[3]);//ArrayIndexOutOfBoundsException: 3
//子類需要在上否則,子類多餘,父類可以完成全部功能,通過父類完成實際上是一種多態
3. 一個try對應最頂層的catch(處理完一個注釋掉,再處理另一個)
5.Throwable類列印異常信息
String getMessage() 簡短描述
String toString() 詳細消息
void printStackTrace() 最全面的
System.out.println(e.getMessage());//文件的後綴名不對呀
System.out.println(e);//java.io.IOException: 文件的後綴名不對呀
System.out.println(e.toString());//重寫Object類的toString java.io.IOException: 文件的後綴名不對呀
e.printStackTrace();//有多少打多少
6.自定義異常
自定義異常類必須以Exception結尾,代表它是一個異常類自定義異常類必須繼承Exception或者RuntimeException其一public class XXXExcepiton extends Exception | RuntimeException{
添加一個空參數的構造方法
添加一個帶異常信息的構造方法
public class RegisterException extends /*Exception*/ RuntimeException{
//添加一個空參數的構造方法
public RegisterException(){
super();
public RegisterException(String message){
super(message);
1)自定義異常demo
/*
要求:我們模擬註冊操作,如果用戶名已存在,則拋出異常並提示:親,該用戶名已經被註冊。
分析:
1.使用數組保存已經註冊過的用戶名(資料庫)
2.使用Scanner獲取用戶輸入的註冊的用戶名(前端,頁面)
3.定義一個方法,對用戶輸入的中註冊的用戶名進行判斷
用輸入的用戶名和數組保存的用戶名比較
true:
用戶名已經存在,拋出RegisterException異常,告知用戶"親,該用戶名已經被註冊";
false:
繼續遍歷比較到循環結束,還沒有找到重複的用戶名,提示用戶"恭喜您,註冊成功!";
*/
public class DemoRegisterException {
// 1.使用數組保存已經註冊過的用戶名(資料庫)
static String[] usernames = {"張三","李四","王五"};
public static void main(String[] args) throws RegisterException {
//2.使用Scanner獲取用戶輸入的註冊的用戶名(前端,頁面)
Scanner sc = new Scanner(System.in);
System.out.println("請輸入您要註冊的用戶名:");
String username = sc.next();
checkUsername(username);
//3.定義一個方法,對用戶輸入的中註冊的用戶名進行判斷
public static void checkUsername(String username) throws RegisterException {
//遍歷存儲已經註冊過用戶名的數組,獲取每一個用戶名
for (String name : usernames) {
//使用獲取到的用戶名和用戶輸入的用戶名比較
if(name.equals(username)){
//true:用戶名已經存在,拋出RegisterException異常,告知用戶"親,該用戶名已經被註冊";
throw new RegisterException("親,該用戶名已經被註冊");//拋出運行期異常,無需處理,交給JVM處理,中斷處理
//如果循環結束了,還沒有找到重複的用戶名,提示用戶"恭喜您,註冊成功!";
System.out.println("恭喜您,註冊成功!");
//也可以不throws,用try