一文帶你深入認識JAVA中的異常
一. 異常概念與體系結構:
1 異常的概念:在 Java 中,將程序執(zhí)行過程中發(fā)生的 不正常行為 稱為異常,
如:算數異常: ArithmeticException
System.out.println(10 / 0); // 執(zhí)行結果 Exception in thread "main" java.lang.ArithmeticException: / by zero
數組越界異常:ArrayIndexOutOfBoundsException
int[] arr = {1, 2, 3}; System.out.println(arr[100]); // 執(zhí)行結果 Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 100
空指針異常: NullPointerException
int[] arr = null; System.out.println(arr.length); // 執(zhí)行結果 Exception in thread "main" java.lang.NullPointerException
2.異常的體系結構:異常種類繁多,為了對不同異?;蛘咤e誤進行很好的分類管理, Java 內部維護了一個 異常的體系結構 如圖:
從圖中可以看出:
(1).Throwable : 是異常體系的頂層類,其派生出兩個重要的子類, Error 和 Exception
(2). Error:指的是Java虛擬機無法解決的嚴重問題,比如:JVM的內部錯誤、資源耗盡等,典型代表: StackOverflowError和OutOfMemoryError,一旦發(fā)生回力乏術。
(3).Exception : 異常產生后程序員可以通過代碼進行處理,使程序繼續(xù)執(zhí)行。比如:感冒、發(fā)燒。我們平時所說的異常就是Exception。
OutOfMemoryError為內存泄漏 :程序中存在未釋放的內存資源,導致內存占用不斷增加,最終導致內存不足等等
StackOverflowError為:無限遞歸下去導致, 超出棧的容量等等
3. 異常的分類:分為 編譯時異常, 運行時異常。
(1). 編譯時異常: 在程序 編譯期間 發(fā)生的異常,稱為 編譯時異常 ,也稱為 受檢查異常
如圖:這個重寫,克隆方法的拷貝,沒有對其捕獲或聲明
下圖則是聲明: 就編譯通過
2. 運行時異常:
(1) 在程序 執(zhí)行期間 發(fā)生的異常,稱為運行時異常,也稱為 非受檢查異常
(2)RunTimeException以及其子類對應的異常,都稱為運行時異常。
比如NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException。
注意:編譯時出現的語法性錯誤,不能稱之為異常。例如將 System.out.println 拼寫錯了, 寫成了
這里也用克隆舉例子,這里沒有實現克隆接口,卻編譯通過了?。?!
但是運行會有異常:這就是非受查異常
二. 異常的處理:
在Java中, 異常處理主要的 5 個關鍵字: throw 、 try 、 catch 、 final 、 throws 。用好他們就,可以很好的處理異常了。
1. 異常的拋出 :在Java中,可以借助throw關鍵字,拋出一個指定的異常對象,將錯誤信息告知給調用者
注意:
(1). throw必須寫在方法體內部
(2). 拋出的對象必須是Exception 或者 Exception 的子類對象
(3). 如果拋出的是 RunTimeException 或者 RunTimeException 的子類,則可以不用處理,直接交給JVM來處理
(4). 如果拋出的是編譯時異常,用戶必須處理,否則無法通過編譯
(5). 異常一旦拋出, 其后 的代碼就不會執(zhí)行。
如圖:這里還用了,try處理catch捕捉
public static void main(String[] args)throws ArrayIndexOutOfBoundsException { int[] array = new int[2]; //捕捉異常 try { //放可能發(fā)生的異常 System.out.println(array[3]); System.out.println("這里不會再執(zhí)行了"); }catch (ArrayIndexOutOfBoundsException e) { //捕捉異常 System.out.println("處理了ArrayIndexOutOfBoundsException異常"); //捕捉,打印異常 e.printStackTrace(); } }
2.異常的捕獲:異常的捕獲,也就是異常的具體處理方式,主要有兩種: 異常聲明throws 以及 try-catch捕獲處理。
拋出異常:
public static void OpenConfig(String filename) throws FileNotFoundException { if (filename.equals("config.ini")) { throw new FileNotFoundException("配置文件名字不對"); } }
3.try-catch 捕獲并處理 :throws對異常并沒有真正處理,而是將異常報告給拋出異常方法的調用者,由調用者處理。如果真正要對異常進行處理,就需要try-catch。)
此時聲明一下,然后捕獲:( 直接聲明不捕獲也可以 )
class Exception { File file; /* FileNotFoundException : 編譯時異常,表明文件不存在 此處不處理,也沒有能力處理,應該將錯誤信息報告給調用者,讓調用者檢查文件名字是否給錯誤了 */ public static void OpenConfig(String filename) throws FileNotFoundException { if (filename.equals("config.ini")) { throw new FileNotFoundException("配置文件名字不對"); } } //捕獲 public static void main(String[] args) { try { //將可能出現異常的代碼放在這里 OpenConfig("test"); } catch (FileNotFoundException e) { // 如果try中的代碼拋出異常了,此處catch捕獲時異常類型與try中拋出的異常類型一致時,或者是try中拋出異常的基就會時,就會被捕獲到 e.printStackTrace(); }finally { // 此處代碼一定會被執(zhí)行到,一般用來關閉文件,釋放資源 } } }
注意:1.try塊內拋出異常位置之后的代碼將不會被執(zhí)行。
2. 如果 拋出異常類型與catch時異常類型不匹配 ,即異常不會被成功捕獲,也就不會被處理,繼續(xù)往外拋 ,直到 JVM收到后中斷程序。 (一般寫法是,用父類異常在最后面兜底)
4.finally:
在寫程序時, 有些特定的代碼,不論程序是否發(fā)生異常,都需要執(zhí)行,比如程序中打開的資源 :網絡連接、數據庫連接、IO 流等, 在程序正?;蛘弋惓M顺鰰r,必須要對資源進進行回收 。另外,因為 異常會引發(fā)程序的跳轉,可能導致有些語句執(zhí)行不到 , finally 就是用來解決這個問題的。
還有 finally 中的代碼一定會執(zhí)行的,一般在 finally 中進行一些資源清理的掃尾工作
語法格式: try{ // 可能會發(fā)生異常的代碼 }catch(異常類型 e){ // 對捕獲到的異常進行處理 }finally{ // 此處的語句無論是否發(fā)生異常,都會被執(zhí)行到 } // 如果沒有拋出異常,或者異常被捕獲處理了,這里的代碼也會執(zhí)行
(補充)異常的處理流程: 如果本方法中沒有合適的處理異常的方式, 就會沿著調用棧向上傳遞 ( 方法1--》方法2--》方法3---》main方法----》jvm)
三. 自定義異常類:
Java 中雖然已經內置了豐富的異常類, 但是并不能完全表示實際開發(fā)中所遇到的一些異常,此時就需要維護符合我們實際情況的異常結構.就需要自定義異常
例如, 我們實現一個用戶登陸功能:
根據業(yè)務此時我們在處理用戶名密碼錯誤的時候可能就需要拋出兩種異常
注意:
1.自定義異常類,然后繼承自Exception 或者 RunTimeException
2. 實現一個帶有String類型參數的構造方法,參數含義:出現異常的原因
業(yè)務代碼:
class login { private String userName; private String passWord; public void loginFo(String userName, String passWord)throws UserException,PassWardException{ if (!this.userName.equals(userName)) { throw new UserException("拋出自定義,的用戶名錯誤異常"); } if (!this.passWord.equals(passWord)) { throw new PassWardException("拋出密碼自定義,的用密碼錯誤異常"); } System.out.println("登錄成功!"); } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } } public class TestException { public static void main(String[] args) throws UserException { login login = new login(); login.setPassWord("321"); login.setUserName("haha"); login.loginFo("haha", "323"); /*try { login.loginFo("haha", "323"); }catch (UserException e) { e.printStackTrace(); }catch (PassWardException e) { e.printStackTrace(); }finally { }*/ } }
總結
到此這篇關于JAVA中異常的文章就介紹到這了,更多相關JAVA異常內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java?IO流—異常及捕獲異常處理?try…catch…finally
這篇文章主要介紹了Java?IO流—異常及捕獲異常處理?try…catch…finally,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12使用SpringBoot與EasyExcel實現復雜的導入導出
這篇文章主要介紹了使用SpringBoot與EasyExcel實現復雜的導入導出,EasyExcel是一個快速解決大文件內存溢出的Excel處理工具,它能讓你在不用考慮性能、內存等因素的情況下,快速完成Excel的讀、寫等功能,需要的朋友可以參考下2023-10-10elasticsearch集群cluster?discovery可配式模塊示例分析
這篇文章主要為大家介紹了elasticsearch集群cluster?discovery可配式模塊示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-04-04java使用randomaccessfile在文件任意位置寫入數據
Java在文件任意位置寫入數據可以使用RandomAccessFile方法來完成,下面看一個簡單的示例就明白了2014-01-01Java?Thread.currentThread().getName()?和?this.getName()區(qū)別詳
本文主要介紹了Thread.currentThread().getName()?和?this.getName()區(qū)別詳解,TestThread?testThread?=?new?TestThread();2022-02-02