在前期所有的文章中,我們都是假設用戶輸入的引數都是有效的,自己寫的代碼都是沒有bug的,
但是在現實生活中,這并不實際,比如:登陸某一個賬戶,密碼錯誤或賬號錯誤等等,如果確實是錯誤了,應該向用戶提示這類資訊,并在密碼錯誤后,應該進行適當的處理,所以出現了例外,使用例外應該做到以下幾點:
- 向用戶通知錯誤
- 保存所有的作業
- 允許用戶妥善地退出程式
對于例外情況,例如,可能造成程式崩潰的錯誤輸入,java使用了一種稱為例外處理的錯誤捕獲機制,具體到底是什么?我們往下看!!!

前期文章
前言- IDEA如何配置?讓你敲代碼更輕松!
初識Java語言(一)- 基本資料型別及運算子
初識Java語言(二)- 方法以及遞回
初識Java語言(三)- 陣列
初識Java語言(四)-類和物件
初識Java語言(五)- 包和繼承
初識Java語言(六)-多型、抽象類以及介面
初識Java語言(七)- String、StringBuilder和StringBuffer的區別
文章目錄
- 一、例外的基本用法
- 捕獲例外
- 拋出例外
- 關于finally的說明
- 二、Java例外體系
- 三、自定義例外
一、例外的基本用法
捕獲例外
基本的形式:
try {
//可能會出例外的代碼
} catch(可能會出例外的 例外型別) {
//出例外后,應該向用戶做什么提示
} finally {
//不管try中的代碼會不會產生例外,finally的代碼都會執行
}
- try:里面放著的就是可能會產生例外的代碼
- catch:括號里是可能出現例外的例外名,花括號里就是需要向用戶提示的例外資訊
- finally:不管try里面會不會產生例外,finally都會被執行,也就是做善后作業
- catch和finally陳述句可以選擇有和沒有,當然catch陳述句,也可以寫多句,
int[] arr = new int[10]; //長度為10的陣列
System.out.println("越界訪問之前");
System.out.println(arr[11]); //越界訪問
System.out.println("越界訪問之后");
以上的代碼,運行之后,會拋出以下例外:

圖上已經很清晰的說出了問題,在越界訪問之前的代碼還是能夠正常的執行,但是在越界訪問之后,以下的代碼就沒運行了,也就是說,在發生陣列越界例外后,這個例外沒有自己手動的去處理了,那么會自動地交給JVM來處理,JVM的處理方式就是終止程式的運行,所以也就不會輸出“越界訪問之后”,這一段文字,
手動處理:

我們可以自己手動地處理這些例外,然后可以使代碼繼續地執行下去,
當然我們還得注意一個問題,那就是在try陳述句里面如果產生了例外,從產生例外的位置開始,往下一直到try陳述句完,這一范圍內的陳述句都不會被執行,如圖:

例外的處理流程:
- 程式會先執行try陳述句里面的代碼
- try陳述句里面沒有產生例外,那么就不會進入catch陳述句里面,如果產生了例外,并且和catch圓括號里的例外名匹配成功,那么就會執行catch里面的陳述句;如果產生的例外沒有匹配成功,那么這個例外會往上次呼叫方回傳去,
- 如果上次呼叫方,也沒有處理相應的例外,會一直往上層回傳,知道main方法處,還沒處理,就會交給JVM處理,此時程式就會終止,
- 無論是否會產生例外,finally里面的陳述句都會執行,
拋出例外
在上文中,我們只是知道了如何處理系統自己產生的例外,現在我們來看一看,我們自己如何去產生(拋出)一個例外,
//假設現在我們需要輸入兩個引數:
//1-》 開始游戲
//0-》退出游戲
//結果用戶在輸入的時候,輸入既不是1也不是0,那么此時我們就可以自己手動地產生一個例外
Scanner sc = new Scanner(System.in);
System.out.println("1-> 開始游戲 0->退出游戲");
int n = sc.nextInt();
if (n != 1 && n != 0) {
throw new RuntimeException("輸入引數非法");
}

如上圖,我們可以通過throw new后面接著寫例外名,就可以手動地產生一個例外,
我們在需要呼叫別人寫的方法時,不知道方法里面具體會產生哪些例外,所以有一種解決方法,就是在方法名后面用throws來提示呼叫這個方法的人,需要處理一下這些例外,比如如下代碼:
public boolean login() throws RuntimeException {
//假設現在我們需要輸入兩個引數:
//1-》開始游戲
//0-》退出游戲
//結果用戶在輸入的時候,輸入既不是1也不是0,那么此時我們就可以自己手動地產生一個例外
Scanner sc = new Scanner(System.in);
System.out.println("1-> 開始游戲 0->退出游戲");
int n = sc.nextInt();
if (n != 1 && n != 0) {
throw new RuntimeException("輸入引數非法");
}
}
像上面這樣寫的代碼,就能夠顯示地提示呼叫這個方法的人,需要處理一下throws后面的例外,
關于finally的說明
在上文中,我們都知道,try陳述句里面的代碼,無論是否會產生例外,我們都會執行finally陳述句,那么以下代碼,會是什么樣的結果:
public static void main(String[] args) {
System.out.println(func()); //會輸出什么結果?
}
public static int func() {
try{
return 10;
} finally {
return 20;
}
}
上述代碼,會列印什么結果?
大家可能就會說,第7行代碼,直接就回傳10了,也就是結束了當前方法,實則并不然,finally還是會執行的,此時回傳的還是finally陳述句中的20,

二、Java例外體系
Java中例外的大致框架如下:

圖中,紅色字體部分,稱為檢查型例外;RuntimeException分支下的所有例外以及Error,都是非檢查型例外,
- 頂層類 Throwable 派生出兩個重要的子類, Error 和 Exception
- 其中 Error 指的是 Java 運行時內部錯誤和資源耗盡錯誤. 應用程式不拋出此類例外. 這種內部錯誤一旦出現,除了告知用戶并使程式終止之外, 再無能無力. 這種情況很少出現.
- Exception 是我們程式猿所使用的例外類的父類.
- 其中 Exception 有一個子類稱為 RuntimeException , 這里面又派生出很多我們常見的例外類NullPointerException , IndexOutOfBoundsException 等
如果一段代碼可能拋出檢查型例外,那么必須顯示地處理這些例外,比如用try,catch處理;又或者是throws拋給上層呼叫者,
三、自定義例外
雖然Java的實作者給我們提供了很多豐富的例外類,但是有時候Java底層實作的例外類,并不能夠滿足人們的需求,所以我們還可以自己來設計一個例外類,怎么設計?很簡單,設計一個類,繼承與Java底層已經實作的類,即可,
class MyException extends RuntimeException {
public MyException() {
}
public MyException(String name) {
super(name);
}
}
像上面的代碼一樣,我們只需要提供兩個構造方法,即可實作自己的例外類,
自定義例外注意實作:
- 自定義例外通常繼承于
Exception或者RuntimeException - 繼承于Exception,默認是檢查型例外,也就是需要顯示地拋出例外
- 繼承于RuntimeException,默認是非檢查型例外,
在文章的最后,還有一道非常有意思的問題:

上下兩個紅框的代碼,有什么區別???又或者說有什么問題??
解釋:在產生例外的時候,JVM會自動地去查找下一條catch陳述句,也就是說,它會從上往下依次查找匹配的例外,如果匹配成功,就執行catch陳述句;當catch陳述句執行完后,不會進入下一條catch陳述句,
所以我們可以發現第二個框中的陳述句,第一條catch陳述句就是用Exception來捕獲,那么只要是一個例外,都會被第一個catch所捕獲,那么下面的第2個、第3個寫的例外,就沒什么用的,一旦產生例外,不會輪流到下面這兩個catch陳述句來捕獲的,
所以我們在寫try,catch陳述句時,catch陳述句的手寫形式,從上往下,例外的等級應越來越高,如上圖中,第一個紅框的書寫形式,
好啦,本期更新就到此結束啦!我們下期見!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/303091.html
標籤:其他
