【JavaSE】基礎筆記 - 異常(Exception)

?目錄

1、異常的概念和體系結構

1.1、異常的概念

1.2、?異常的體系結構

1.3 異常的分類?

2、異常的處理

2.1、防御式編程

2.2、異常的拋出

2.3、異常的捕獲

2.3.1、異常聲明throws

2.3.2、try-catch捕獲并處理

3、自定義異常類


?

1、異常的概念和體系結構

1.1、異常的概念

在日常開發中,絞盡腦汁將代碼寫的盡善盡美,在程序運行過程中,難免會出現一些奇奇怪怪的問題。有時通過代碼很難去控制,比如:數據格式不對、網絡不通暢、內存報警等。

當出現這些問題時,JVM虛擬機會自動捕獲這些問題并拋出錯誤信息。在Java中,將程序執行過程中發生的不正常行為稱為異常。

例如:

(1)算術異常

System.out.println(10 / 0);

(2)數組越界異常

int[] arr = {1, 2, 3};
System.out.println(arr[100]);

(3)空指針異常

int[] arr = null;
System.out.println(arr.length);

從上述過程中可以看到,java中不同類型的異常,都有與其對應的類來進行描述。?

1.2、?異常的體系結構

異常種類繁多,為了對不同異常或者錯誤進行很好的分類管理,Java內部維護了一個異常的體系結構:

從上圖中可以看到:

  1. Throwable:是異常體系的頂層類,其派生出兩個重要的子類, ErrorException
  2. Error:指的是Java虛擬機無法解決的嚴重問題,比如:JVM的內部錯誤、資源耗盡等,典型代表:StackOverflowError和OutOfMemoryError,一旦發生回力乏術。
  3. Exception:異常產生后程序員可以通過代碼進行處理,使程序繼續執行。比如:感冒、發燒。我們平時所說的異常就是Exception。

1.3 異常的分類?

異常可能在編譯時發生,也可能在程序運行時發生,根據發生的時機不同,可以將異常分為:

1. 編譯時異常

在程序編譯期間發生的異常,稱為編譯時異常,也稱為受檢查異常(Checked Exception)

2. 運行時異常

在程序執行期間發生的異常,稱為運行時異常,也稱為非受檢查異常(Unchecked Exception)
RunTimeException以及其子類對應的異常,都稱為運行時異常。

比如:NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException。

注意:編譯時出現的語法性錯誤,不能稱之為異常。例如將 System.out.println 拼寫錯了, 寫成了system.out.println. 此時編譯過程中就會出錯, 這是 "編譯期" 出錯。而運行時指的是程序已經編譯通過得到class 文件了, 再由 JVM 執行過程中出現的錯誤。

2、異常的處理

2.1、防御式編程

錯誤在代碼中是客觀存在的. 因此我們要讓程序出現問題的時候及時通知程序猿。主要的方式

?1. LBYL: Look Before You Leap. 在操作之前就做充分的檢查。即:事前防御型

boolean ret = false;ret = 登陸游戲();if (!ret) {處理登陸游戲錯誤;return;}ret = 開始匹配();if (!ret) {處理匹配錯誤;return;}ret = 游戲確認();if (!ret) {處理游戲確認錯誤;return;}ret = 選擇英雄();if (!ret) {處理選擇英雄錯誤;return;}ret = 載入游戲畫面();if (!ret) {處理載入游戲錯誤;return;}

?缺陷:正常流程和錯誤處理流程代碼混在一起, 代碼整體顯的比較混亂。

2. EAFP: It's Easier to Ask Forgiveness than Permission. "事后獲取原諒比事前獲取許可更容易". 也就是先操作, 遇到問題再處理. 即:事后認錯型

        try {登陸游戲();開始匹配();游戲確認();選擇英雄();載入游戲畫面();
...} catch (登陸游戲異常) {處理登陸游戲異常;} catch (開始匹配異常) {處理開始匹配異常;} catch (游戲確認異常) {處理游戲確認異常;} catch (選擇英雄異常) {處理選擇英雄異常;} catch (載入游戲畫面異常) {處理載入游戲畫面異常;}

優勢:正常流程和錯誤流程是分離開的, 程序員更關注正常流程,代碼更清晰,容易理解代碼?

2.2、異常的拋出

在編寫程序時,如果程序中出現錯誤,此時就需要將錯誤的信息告知給調用者,比如:參數檢測。
在Java中,可以借助throw關鍵字,拋出一個指定的異常對象,將錯誤信息告知給調用者。具體語法如下:

throw new XXXException("異常產生的原因");

【注意事項】

  1. throw必須寫在方法體內部
  2. 拋出的對象必須是Exception 或者 Exception 的子類對象
  3. 如果拋出的是 RunTimeException 或者 RunTimeException 的子類,則可以不用處理,直接交給JVM來處理
  4. 如果拋出的是編譯時異常,用戶必須處理,否則無法通過編譯
  5. 異常一旦拋出,其后的代碼就不會執行(除非使用try-catch捕捉可能異常代碼)

2.3、異常的捕獲

異常的捕獲,也就是異常的具體處理方式。

主要有兩種:異常聲明throws 以及 try-catch捕獲處理。

2.3.1、異常聲明throws

處在方法聲明時參數列表之后,當方法中拋出編譯時異常,用戶不想處理該異常,此時就可以借助throws將異常拋給方法的調用者來處理。即當前方法不處理異常,提醒方法的調用者處理異常。

語法格式:
修飾符 返回值類型 方法名(參數列表) throws 異常類型1,異常類型2...{}

【注意事項】

  1. throws必須跟在方法的參數列表之后。
  2. 聲明的異常必須是 Exception 或者 Exception 的子類。
  3. 方法內部如果拋出了多個異常,throws之后必須跟多個異常類型,之間用逗號隔開,如果拋出多個異常類型具有父子關系,直接聲明父類即可。
  4. 調用聲明拋出異常的方法時,調用者必須對該異常進行處理,或者繼續使用throws拋出。

2.3.2、try-catch捕獲并處理

throws對異常并沒有真正處理,而是將異常報告給拋出異常方法的調用者,由調用者處理。如果真正要對異常進行處理,就需要try-catch

語法格式:

    public static void main(String[] args) {try {// 將可能出現異常的代碼放在這里} catch (要捕獲的異常類型 e) {// 如果try中的代碼拋出異常了,此處catch捕獲時異常類型與try中拋出的異常類型一致時,或者是try中拋出異常的基類時,就會被捕獲到// 對異常就可以正常處理,處理完成后,跳出try-catch結構,繼續執行后序代碼} finally {// 此處代碼一定會被執行到}// 后序代碼// 當異常被捕獲到時,異常就被處理了,這里的后序代碼一定會執行// 如果捕獲了,由于捕獲時類型不對,那就沒有捕獲到,這里的代碼就不會被執行}

finally是什么?

finally中代碼是一定會被執行的。

在寫程序時,有些特定的代碼,不論程序是否發生異常,都需要執行,比如程序中打開的資源:網絡連接、數據庫連接、IO流等,在程序正常或者異常退出時,必須要對資源進進行回收。另外,因為異常會引發程序的跳轉,可能導致有些語句執行不到finally就是用來解決這個問題的。?

注意:不是說放在try中的代碼就一定會拋出異常,只是在try內寫的代碼在拋出異常時會被捕捉到。需要理解一個誤區。?

關于異常的處理方式

異常的種類有很多, 我們要根據不同的業務場景來決定.

對于比較嚴重的問題(例如和算錢相關的場景), 應該讓程序直接崩潰, 防止造成更嚴重的后果

對于不太嚴重的問題(大多數場景), 可以記錄錯誤日志, 并通過監控報警程序及時通知程序猿

對于可能會恢復的問題(和網絡相關的場景), 可以嘗試進行重試。

我們記錄的錯誤日志是出現異常的方法調用信息, 能很快速的讓我們找到出現異常的位置. 以后在實際工作中我們會采取更完備的方式來記錄異常信息。

【異常處理的流程總結】

  • 程序先執行 try 中的代碼。
  • 如果 try 中的代碼出現異常, 就會結束 try 中的代碼, 看和 catch 中的異常類型是否匹配。
  • 如果找到匹配的異常類型, 就會執行 catch 中的代碼。
  • 如果沒有找到匹配的異常類型, 就會將異常向上傳遞到上層調用者。
  • 無論是否找到匹配的異常類型, finally 中的代碼都會被執行到(在該方法結束之前執行)。
  • 如果上層調用者也沒有處理的了異常, 就繼續向上傳遞。
  • 一直到 main 方法也沒有合適的代碼處理異常, 就會交給 JVM 來進行處理, 此時程序就會異常終止。

3、自定義異常類

自定義異常類必須繼承自Exception或者RunTimeException,并且實現一個帶有String類型參數的構造方法,參數含義:出現異常的原因

例如, 我們實現一個用戶登陸功能

//用于判斷用戶名的異常類
public class UserNameException extends RuntimeException{public UserNameException() {super();}public UserNameException(String s) {super(s);}
}
//用于判斷密碼的異常類
public class UserPasswordException extends RuntimeException {public UserPasswordException() {super();}public UserPasswordException(String s) {super(s);}
}

用戶進行登錄,用戶名或者密碼錯誤時需要提示用戶名或密碼錯誤,但是如果直接使用println打印,那么只能知道錯了,但是無法得知是錯在哪一行,而使用自定義異常類就能解決這個問題,方便程序員在大型工程中快速找到報錯地方

class Login {public String userName = "admin";public String passWord = "123456";public void login(String userName, String passWord) {if(!this.userName.equals(userName)) {//System.out.println("用戶名錯誤!");//使用自定義異常類來提示用戶名錯誤throw new UserNameException("用戶名錯誤!");}if(!this.passWord.equals(passWord)) {//System.out.println("密碼錯誤!");//使用自定義異常類來提示密碼錯誤throw new UserPasswordException("密碼錯誤!");}}
}public class Main {public static void main(String[] args) {try {Login l = new Login();l.login("admin", "123");} catch (UserNameException | UserPasswordException e) {e.printStackTrace();}}
}

?【運行結果】

【注意事項】?

  • 自定義異常通常會繼承自 Exception 或者 RuntimeException。
  • 繼承自 Exception 的異常默認是受查異常。
  • 繼承自 RuntimeException 的異常默認是非受查異常。

?

?博主推薦:

?【計算機組成原理】知識點鞏固 - 存儲器概述-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/134482974?spm=1001.2014.3001.5502

【JavaSE】基礎筆記 - 圖書管理系統(保姆教程,含源碼)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/134467911?spm=1001.2014.3001.5502

【JavaSE】基礎筆記 - 類和對象(下)-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zzzzzhxxx/article/details/134248822?spm=1001.2014.3001.5502?

如果覺得作者寫的不錯,求給博主一個大大的點贊支持一下,你們的支持是我更新的最大動力!

如果覺得作者寫的不錯,求給博主一個大大的點贊支持一下,你們的支持是我更新的最大動力!

如果覺得作者寫的不錯,求給博主一個大大的點贊支持一下,你們的支持是我更新的最大動力!

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/165307.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/165307.shtml
英文地址,請注明出處:http://en.pswp.cn/news/165307.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

datasets.Dataset.map方法學習筆記

Dataset.map 方法概要 可以將datasets中的Dataset實例看做是一張數據表。map方法會將輸入的function按照指定的方式應用在每一行(每一行稱為一個example)上。本文采用一下示例進行說明: from datasets import Dataset # datasets.__versi…

前端開發工具集合

文章目錄 Visual Studio Code (VS Code)安裝及配置一、安裝二、常用插件三、相關配置四、統一配置代碼 Visual Studio Code (VS Code)安裝及配置 一、安裝 下載地址:https://code.visualstudio.com/ ?> VS Code 下載慢,解決辦法請點擊 雙擊下載文件…

Java零基礎——SpringMVC篇

1.SpringMVC介紹 SpringMVC是Spring框架中的一個組件,是一個輕量級的web的MVC框架,充當controller,其本質就是一個Servlet。 1.1 傳統Servlet的不足 每個請求,都需要定義一個Servlet。雖然可以在service方法中,根據業務標識進行…

【Linux 帶寬限速】trickle,限制docker 上傳速度

限制docker 上傳速度 然而,你可以使用第三方工具來實現這個目的。一個常用的工具是 trickle,它可以模擬網絡帶寬。 首先,你需要安裝 trickle。在 Ubuntu 上,可以使用以下命令安裝: sudo apt-get install trickle然后…

deepxde 源碼閱讀筆記(長期更新)

2023.11.23 閱讀的deepxde version: 1.9.0 1. train_aux_vars ,即pde當中的第三個參數 這個變量的含義困惑很久。最后發現就是operator learning的PDEs方程parameters。 脈絡:def pde aux_vars-> deepxde目前支持tf1最多,但是對其他框架…

系列二、Spring整合單元測試

一、概述 Spring中獲取bean最常見的方式是通過ClassPathXmlApplicationContext 或者 AnnotationConfigApplicationContext的getBean()方式獲取bean,那么在Spring中如何像在SpringBoot中直接一個類上添加個SpringBootTest注解,即可在類中注入自己想要測試…

優秀的企業協同OA系統如何促進團隊協作?

優秀的企業協同OA系統可以幫助團隊協同工作變得更簡單、更高效。 一、以下是一些優秀的企業協同OA系統可以幫助團隊協作的方法: 1、提高工作效率 優秀的企業協同OA系統可以提高工作效率,減少工作的重復性和低效率。例如,可以使用共享日歷和…

vue2生命周期

前言 vue的生命周期其實可以分為兩塊,一個是vue實例的生命周期,一個是組件的生命周期。 vue實例的生命周期方法共有4個:$mout,$forceUpdate,$nextTick,$destroy vue組件的生命周期鉤子共有8個:beforeCreate,created,beforeMount,mounted,beforeUpdate, updated,beforeDestr…

C/C++小寫字母的判斷 2022年3月電子學會中小學生軟件編程(C/C++)等級考試一級真題答案解析

目錄 C/C小寫字母的判斷 一、題目要求 1、編程實現 2、輸入輸出 二、算法分析 三、程序編寫 四、程序說明 五、運行結果 六、考點分析 C/C小寫字母的判斷 2022年3月 C/C編程等級考試一級編程題 一、題目要求 1、編程實現 輸入一個字符,判斷是否是英文小…

iframe內部子頁面與外部主頁面通訊

文章目錄 一、問題二、解決2.1、子頁面2.2、主頁面 三、知識點3.1、[瀏覽器兼容性](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage#%E6%B5%8F%E8%A7%88%E5%99%A8%E5%85%BC%E5%AE%B9%E6%80%A7)3.2、詳解3.2.1、發送方3.2.2、接收方 一、問題 如上所示&a…

被刪數據庫+勒索

被刪數據庫勒索 – WhiteNights Site 標簽:日志 快照在手,天下我有 服務器又給人黑了。這次是給人黑了數據庫,被人刪庫勒索,先放圖吧。我還花了今天一個下午的時間查修這個漏洞,導致網站有接近6個小時都沒法訪問。 …

編程示例: Session Id的生成

實現思路 Session的實現方式如下:在用戶第一次登錄的時候,系統為它分配一個唯一Id(被稱為Session Id)作為標識,并且 記錄下這個用戶的用戶名、要登錄的賬套名、用戶擁有的權限等,以Id為鍵,用戶名、賬套名等信息為值保…

云原生Kubernetes系列 | Kubernetes靜態Pod的使用

云原生Kubernetes系列 | Kubernetes靜態Pod的使用 靜態pod不建議在master上操作,因為master上跑的是集群核心靜態pod,如果配置失敗,會導致集群故障。建議在knode1或knode2上去做。 kubernetes master節點上的核心組件pod其實都是靜態pod: [root@k8s-master ~]# ls /etc/ku…

java中鎖的使用-實戰

技術主題 技術原理 在實際的業務中,為了保證線程安全,會進行對一些邏輯進行加鎖,保證當前只有一個線程在操作。在代碼中,我們經常使用兩種方式進行加鎖,來保證線程安全。一種是synchronized關鍵字,另一種是ReentrantLock加鎖。寫這一份的博客,就是為了記錄下鎖的基本使…

五分鐘,Docker安裝flink,并使用flinksql消費kafka數據

1、拉取flink鏡像,創建網絡 docker pull flink docker network create flink-network2、創建 jobmanager # 創建 JobManager docker run \-itd \--namejobmanager \--publish 8081:8081 \--network flink-network \--env FLINK_PROPERTIES"jobmanager.rpc.ad…

Redis 命令行 redis-cli 介紹

文章目錄 前言1. 連接 Redis 服務2. 從其他程序獲取輸入3. 連續執行相同的命令4. CSV 輸出5. 輸出幫助信息6. 清空屏幕7. 連續監控統計信息8. 輸出大 key 報告9. 監控 Redis 執行的命令 前言 redis-cli 是 Redis 自帶的命令行工具,是運維和開發人員常用的工具&…

【C++干貨鋪】適配器 | stack | queue

個人主頁點擊直達:小白不是程序媛 C系列學習專欄:C干貨鋪 代碼倉庫:Gitee 目錄 stack的介紹和使用 stack的介紹 stack的使用 queue的介紹和使用 queue的介紹 queue的使用 容器適配器 什么是適配器 STL中stack和queue的底層結構 d…

Doris擴容和縮容(六)

Doris 可以很方便的擴容和縮容 FE、BE、Broker 實例。 FE 擴容和縮容 可以通過將 FE 擴容至 3 個以上節點來實現 FE 的高可用。 1)使用 MySQL 登錄客戶端后,可以使用 sql 命令查看 FE 狀態,目前就一臺 FE mysql -h hadoop1 -P 9030 -uroo…

Python——基于YOLOV8的車牌識別(源碼+教程)

目錄 一、前言 二 、完成效果 三、 項目包 四、運行項目 (教程) 一、前言 YOLOv8LPRNet車牌定位與識別https://www.bilibili.com/video/BV1vk4y1E7MZ/ 最近做了有一個車牌識別的小需求,今天完成了,在此記錄和分享 首先&#x…

辦公技巧:Word中插入圖片、形狀、文本框排版技巧

目錄 一、插入圖片排版技巧 二、添加形狀排版技巧 三、插入“文本框”排版技巧 我們平常在制作word時候經常會遇到插入選項卡下的圖片、形狀和文本框這三種情況下,那么如何使得Word文檔當中添加這三個元素的同時,又能保證樣式美觀呢,今天小…