一、異常的描述
程序運行時,發生的不被期望的事件,它阻止了程序按照程序員的預期正常執行,這就是異常。異常發生時,是任程序自生自滅,立刻退出終止。在Java中即,Java在編譯或運行或者運行過程中出現的錯誤。
Java提供了更加優秀的解決辦法:異常處理機制。
異常處理機制能讓程序在異常發生時,按照代碼的預先設定的異常處理邏輯,針對性地處理異常,讓程序盡最大可能恢復正常并繼續執行,且保持代碼的清晰。
Java中的異常可以是函數中的語句執行時引發的,也可以是程序員通過throw 語句手動拋出的,只要在Java程序中產生了異常,就會用一個對應類型的異常對象來封裝異常,JRE就會試圖尋找異常處理程序來處理異常。
- 異常指在運行時期發生的不正常情況。
- 在java中用類的形式對不正常情況進行了描述和封裝對象。
- 描述不正常情況的類,就成為異常類。
- 將正常代碼和問題處理代碼分離,提高閱讀性。
- 其實異常就是java通過面向對象的思想將問題封裝成了對象,用異常類對其進行描述。
二、異常的體系
兩大類:
- hrowable:可拋出的異常,無論是error還是exception,問題發生就應該可以拋出,讓調用者知道并且處理。
- 該體系的特點就是在于Throwable及其所有的子類都具有可拋性。
可拋性到底指的是什么?怎么體現可拋性呢?
- 通過兩個關鍵字來體現的。
- throws throw 凡是可以被這兩個關鍵字所操作的類和對象都具有可拋性。
- 子類1 一般不可處理的。————Error
- 特點:是由jvm拋出的嚴重性問題,這種問題發生一般不針對性處理,直接修改程序。
- 子類2)可以處理的。————Exception,問題拋給調用者,誰用拋給誰。
- 特點:子類后綴名都是用其父類名作為后綴名,閱讀性很強!
范例:比如自定義一個負數角標的異常,使用面向對象思想封裝成對象。
- 注意:如果讓一個類稱為異常類,必須要繼承異常類。因為只有異常體系的子類才具有可拋性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class FuShuIndex extends Exception{ //構造函數 和類名一樣 FuShuIndex(){ } //定義一個帶參數的構造函數 FuShuIndex(String msg){ //調用Exception中的帶參數異常函數 super (msg); } } 主函數 throws FuShuIndex:{ int [] arr = new int [ 3 ]; method(arr,- 7 ); } public static int method( int [] arr, int index) throws arrIndexexception { if (index< 0 ){ throw new arrIndexexception( "數組的角標不能為負數" ); } return arr[index]; } |
三、異常的分類:
編譯時被檢測異常還要是Exception和其子類都是,除了特殊子類RuntimeException體系未處理即編譯失敗!
- 這種問題一旦出現,希望在編譯時就進行檢測,讓這種問題有相應的處理方式,這樣的問題都可以針對性處理。
編譯時不被檢測異常(運行時異常):RuntimeException和其子類
- 可處理可不處理,編譯都可以通過,運行時會檢測!
- 這種問題的發生,無法讓功能繼續,運算無法運行,更多因為調用的原因導致,或者引發了內部狀態的改變導致的。這種問題一般不處理,直接編譯通過,在運行時,讓調用者時程序強制停止,讓調用者對代碼進行修正。
throws和throw的區別:
- throws使用在函數上 ————申明
- throw使用在函數內,可以拋出多個,用逗號隔開。 ————拋出
- throws拋出的是異常類,可以拋出多個。
- throw拋出的是異常對象。
四、異常處理的捕捉形式
這是可以對異常進行針對性處理的方式。
格式:
1
2
3
4
5
6
7
8
9
|
try { //需要被檢測異常的代碼 } catch (異常類 變量) //該變量用于接收發生的異常對象{ //處理異常代碼 } finally { //一定會被執行的代碼 } |
范例
1
2
3
4
5
6
7
8
9
10
|
class FuShuIndex extends Exception{ //構造函數 和類名一樣 FuShuIndex(){ } //定義一個帶參數的構造函數 FuShuIndex(String msg){ //調用Exception中的帶參數異常函數 super (msg); } } |
主函數:無需throws拋出,下面我們自己捕獲異常
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
{ int [] arr = new int [ 3 ]; try { method(arr,- 7 ); } catch (arrIndexexception a){ a.printStackTrace(); //jvm默認的異常處理機制就是調用異常對象的這個方法。 System.out.println( "數組的角標異常!!!" ); //自定義捕獲后打印的信息 System.out.println(a.toString()); //打印該異常對象的信息 System.out.println(a.getMessage()); //獲取我們自定義拋出所定義的信息 } } public static int method( int [] arr, int index) throws arrIndexexception { if (index< 0 ){ throw new arrIndexexception( "數組的角標不能為負數" ); } return arr[index]; } |
一個try對應多個catch:
- 多catch情況下,父類的catch要放在最下面,否則編譯為空。
五、異常處理的原則
函數內部如果拋出了需要檢測的異常,那么函數上必須申明,或者必須在函數內用try catch捕捉,否則編譯失敗。
如果調用到了申明異常的函數,要么try catch 或者 throws ,否則編譯失敗。
什么時候catch?什么時候throws?
- 功能內容可以解決,用catch。
- 解決不了,用throws告訴調用者,由調用者解決。
一個功能如果拋出了多個異常,那么調用時,必須有對應的多個catch來進行針對性處理。
- 內部有幾個需要檢測的異常,就拋幾個異常,拋出幾個就catch幾個異常。
六、finally
通常用于關閉(釋放)資源。必須要執行。除非jvm虛擬機掛了。
范例:出門玩,必須關門,所以將關門這個動作放在finally里面,必須執行。
凡是涉及到關閉連接等操作,要用finally代碼塊來釋放資源。
try catch finally 代碼塊組合特點:
- try catch finally:當有資源需要釋放時,可以定義finally
- try catch(多個):當沒有資源需要釋放時,可以不定義finally
- try finally:異常處理不處理我不管,但是我得關閉資源,因為資源是我開的,得在內部關掉資源。
范例:
1
2
3
4
5
6
7
|
try { //連接數據庫 } //沒有catch意思不處理異常,只單純的捕獲異常 finally { //關閉連接 } |
七、異常的應用
老師用電腦講課范例:
電腦類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public class Computer { private int state = 2 ; public void run() throws lanpingExcption,maoyanExcption{ if (state == 1 ){ throw new lanpingExcption( "電腦藍屏啦~" ); } else if (state == 2 ){ throw new maoyanExcption( "電腦冒煙啦~" ); } System.out.println( "電腦啟動" ); } public void chongqi(){ state = 0 ; System.out.println( "重啟電腦!" ); } } |
老師類:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
public class Teacher { private String name; private Computer computer; Teacher(String name){ this .name = name; computer = new Computer(); } void teach() throws maoyanExcption{ try { computer.run(); System.out.println( this .name + "開始用電腦講課了" ); } catch (lanpingExcption l) { l.printStackTrace(); computer.chongqi(); teach(); //重啟后再次講課 } catch (maoyanExcption m) { m.printStackTrace(); test(); throw m; } } public void test(){ System.out.println( "大家自己練習去~" ); } } |
藍屏異常類:
1
2
3
4
5
|
public class lanpingExcption extends Exception{ lanpingExcption (String msg){ super (msg); } } |
冒煙異常類:
1
2
3
4
5
|
public class maoyanExcption extends Exception { maoyanExcption (String msg){ super (msg); } } |
主函數:
1
2
3
4
5
6
7
8
9
10
11
|
public class Testmain { public static void main (String[] args){ Teacher teacher = new Teacher( "丁老師" ); try { teacher.teach(); } catch (maoyanExcption m) { //m.printStackTrace(); System.out.println( "。。。。。" ); } } } |
八、異常的注意事項:
- 子類在覆蓋父類方法時,父類的方法如果拋出了異常,那么子類的方法只能拋出父類的異常或者該異常的子類。
- 如果父類拋出多個異常,那么子類只能拋出父類異常的子集。
- 子類覆蓋父類,只能拋出父類的異常或者子類。
- 如果父類的方法沒有拋出異常,子類覆蓋時絕對不能拋。
總結
到此這篇關于Java異常類型以及處理的文章就介紹到這了,更多相關Java異常類型及處理內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://juejin.cn/post/6982755671733174309