【Java SE】帶你識別什么叫做異常!!!

在這里插入圖片描述
🌹🌹🌹個人主頁🌹🌹🌹
【🌹🌹🌹Java SE 專欄🌹🌹🌹】
🌹🌹🌹上一篇文章:【Java SE】帶你在String類世界中遨游!!!🌹🌹🌹

文章目錄

  • 1. 異常的概念與體系結構
    • 1.1 異常的概念
    • 1.2 異常的體系結構
    • 1.3 異常的分類
    • 2. 異常的處理
    • 2.1 防御式編程
    • 2.2 異常的拋出(throw)
    • 2.3 異常的捕獲(throws)
    • 2.4 異常的處理流程
      • 3. 自定義異常類

1. 異常的概念與體系結構

1.1 異常的概念

在Java中,將程序執行過程中發生的不正常行為稱為異常。如之前寫代碼時經常遇到的:
1. 算術異常

public static void main1(String[] args) {System.out.println(10/0);//算術異常//Exception in thread "main" java.lang.ArithmeticException: / by zeroat Exception.main(Exception.java:10)}

2. 數組越界異常

public static void main2(String[] args) {int[] array = {1,2,3};for(int i=0;i<=3;i++) {System.out.println(array[i]);//數組越界//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3}}

3. 空指針異常

   public static void main(String[] args) {int[] array = null;System.out.println(array.length);//空指針異常//Exception in thread "main" java.lang.NullPointerException}

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

1.2 異常的體系結構

異常種類繁多,為了對不同異常或者錯誤進行很好的分類管理,Java內部維護了一個異常的體系結構:
在這里插入圖片描述
從上圖中可以看到:

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

1.3 異常的分類

異常可能在編譯時發生,也可能在程序運行時發生,根據發生的時機不同,可以將異常分為:
1. 編譯時異常
在程序編譯期間發生的異常,稱為編譯時異常,也稱為受檢查異常(Checked Exception)

public class Person {
private String name;
private String gender;
int age;
// 想要讓該類支持深拷貝,覆寫Object類的clone方法即可
@Override
public Person clone() {
return (Person)super.clone();
}
}
編譯時報錯:
Error:(17, 35) java: 未報告的異常錯誤java.lang.CloneNotSupportedException; 必須對其進行捕獲或聲明以便拋出

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;

**缺陷:**正常流程和錯誤處理流程代碼混在一起, 代碼整體顯的比較混亂。
2. EAFP: It’s Easier to Ask Forgiveness than Permission. “事后獲取原諒比事前獲取許可更容易”. 也就是先操作, 遇到問題再處理. 即:事后認錯型

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

優勢:正常流程和錯誤流程是分離開的, 程序員更關注正常流程,代碼更清晰,容易理解代碼
異常處理的核心思想就是 EAFP。
在Java中,異常處理主要的5個關鍵字:throw、try、catch、final、throws。
下面我們就來看看這五個關鍵字:

2.2 異常的拋出(throw)

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

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

【需求】:實現一個獲取數組中任意位置元素的方法。

public static int getElement(int[] array, int index){
if(null == array){
throw new NullPointerException("傳遞的數組為null");
}
if(index < 0 || index >= array.length){
throw new ArrayIndexOutOfBoundsException("傳遞的數組下標越界");
}
return array[index];
}
public static void main(String[] args) {
int[] array = {1,2,3};
getElement(array, 3);
}

【注意事項】

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

2.3 異常的捕獲(throws)

異常的捕獲,也就是異常的具體處理方式,主要有兩種:異常聲明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。
語法格式:
try{
// 將可能出現異常的代碼放在這里
}catch(要捕獲的異常類型 e){
// 如果try中的代碼拋出異常了,此處catch捕獲時異常類型與try中拋出的異常類型一致時,或者是try中拋出異常的基類
時,就會被捕獲到
// 對異常就可以正常處理,處理完成后,跳出try-catch結構,繼續執行后序代碼
}[catch(異常類型 e){
// 對異常進行處理
}finally{
// 此處代碼一定會被執行到
}]
// 后序代碼
// 當異常被捕獲到時,異常就被處理了,這里的后序代碼一定會執行
// 如果捕獲了,由于捕獲時類型不對,那就沒有捕獲到,這里的代碼就不會被執行
注意:
1. []中表示可選項,可以添加,也可以不用添加
2. try中的代碼可能會拋出異常,也可能不會

【注意事項】

  1. try塊內拋出異常位置之后的代碼將不會被執行
  2. 如果拋出異常類型與catch時異常類型不匹配,即異常不會被成功捕獲,也就不會被處理,繼續往外拋,直到JVM收到后中斷程序----異常是按照類型來捕獲的
  3. try中可能會拋出多個不同的異常對象,則必須用多個catch來捕獲----即多種異常,多次捕獲
  4. 可以通過一個catch捕獲所有的異常,即多個異常,一次捕獲(不推薦)
    2.3.3 finally
    在寫程序時,有些特定的代碼,不論程序是否發生異常,都需要執行,比如程序中打開的資源:網絡連接、數據庫連接、IO流等,在程序正常或者異常退出時,必須要對資源進進行回收。另外,因為異常會引發程序的跳轉,可能導致有些語句執行不到,finally就是用來解決這個問題的。
語法格式:
try{
// 可能會發生異常的代碼
}catch(異常類型 e){
// 對捕獲到的異常進行處理
}finally{
// 此處的語句無論是否發生異常,都會被執行到
}
// 如果沒有拋出異常,或者異常被捕獲處理了,這里的代碼也會執行

注意:finally中的代碼一定會執行的,一般在finally中進行一些資源清理的掃尾工作。

2.4 異常的處理流程

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

3. 自定義異常類

Java 中雖然已經內置了豐富的異常類, 但是并不能完全表示實際開發中所遇到的一些異常,此時就需要維護符合我們實際情況的異常結構.
例如, 我們實現一個用戶登陸功能:

public class Test {public String name = "admin";public String passWorld = "123456";public  void func(String name, String passWorld) {if(!this.name .equals(name)) {throw new userNameException("用戶名錯誤");}if(!this.passWorld.equals(passWorld)) {throw new passWorldException("密碼錯誤");}}public static void main(String[] args) {Test test = new Test();try {test.func("admin1","123456");} catch (userNameException e) {e.printStackTrace();System.out.println("用戶名輸入異常!");} catch (passWorldException e) {e.printStackTrace();System.out.println("密碼輸入異常!");}finally {System.out.println("結束進程");}}
}

具體方式:

  1. 自定義異常類,然后繼承自Exception 或者 RunTimeException
  2. 實現一個帶有String類型參數的構造方法,參數含義:出現異常的原因

自定義一個userNameException異常類:

public class userNameException extends RuntimeException{public  userNameException() {super();}public userNameException(String name) {super(name);}
}

自定義一個passWorldException異常類:

public class passWorldException extends RuntimeException{public passWorldException() {super();}public passWorldException(String passWorld) {super(passWorld);}
}

注意事項
自定義異常通常會繼承自 Exception 或者 RuntimeException
繼承自 Exception 的異常默認是受查異常
繼承自 RuntimeException 的異常默認是非受查異常.
結尾:
希望大家可以給我點點關注,點點贊,你們的支持就是我的最大鼓勵。🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹🌹

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

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

相關文章

Android獲取Wifi網關

公司有這樣一個應用場景&#xff1a;有一臺球機設備&#xff0c;是Android系統的&#xff0c;它不像手機&#xff0c;它沒有觸摸屏幕&#xff0c;所以我們對球機的操作很不方便&#xff0c;于是我們搞這樣一個設置&#xff1a;點擊球機電源鍵5次分享出一個熱點&#xff0c;然后…

【JVM從入門到實戰】(一) 字節碼文件

一、什么是JVM JVM 全稱是 Java Virtual Machine&#xff0c;中文譯名 Java虛擬機。 JVM 本質上是一個運行在計算機上的程序&#xff0c;他的職責是運行Java字節碼文件。 二、JVM的功能 解釋和運行 對字節碼文件中的指令&#xff0c;實時的解釋成機器碼&#xff0c;讓計算機…

C++類模板不是一開始就創建的,而是調用時生成

類模板中的成員函數和普通類中成員函數創建時機有區別的&#xff1a; 普通類中的成員函數一開始就可以創建模板類中的成員函數調用的時候才可以創建 總結;類模板中的成員函數并不是一開始就創建的&#xff0c;再調用時才去創建 #include<iostream> using namespace st…

微信小程序:模態框(彈窗)的實現

效果 wxml <!--新增&#xff08;點擊按鈕&#xff09;--> <image classimg src"{{add}}" bindtapadd_mode></image> <!-- 彈窗 --> <view class"modal" wx:if"{{showModal}}"><view class"modal-conten…

Vue中$props、$attrs和$listeners的使用詳解

文章目錄 透傳屬性如何禁止“透傳屬性和事件”多根節點設置透傳訪問“透傳屬性和事件” $props、$attrs和$listeners的使用詳解 透傳屬性 透傳屬性和事件并沒有在子組件中用props和emits聲明透傳屬性和事件最常見的如click和class、id、style當子組件只有一個根元素時&#xf…

jOOQ指南中使用的數據庫

jOOQ指南中使用的數據庫 本指南中使用的數據庫將在本節中進行總結和創建 使用Oracle方言來創建 # 創建語言 CREATE TABLE language (id NUMBER(7) NOT NULL PRIMARY KEY,cd CHAR(2) NOT NULL,description VARCHAR2(50) );# 創建作者 CREATE TABLE author (id NUMBER(7) NOT …

mysql:需要準確存儲的帶小數的數據,要使用DECIMAL類型

需要準確存儲的帶小數的數據&#xff0c;要使用DECIMAL&#xff0c;特別是涉及金錢類的業務。而不要使用FLOAT或者DOUBLE。 因為DECIMAL是準確值&#xff0c;不會損失精度。 而FLOAT或者DOUBLE是近似值&#xff0c;會損失精度。 https://dev.mysql.com/doc/refman/8.2/en/fixe…

差生文具多系列之最好看的編程字體

&#x1f4e2;?聲明&#xff1a; &#x1f344; 大家好&#xff0c;我是風箏 &#x1f30d; 作者主頁&#xff1a;【古時的風箏CSDN主頁】。 ?? 本文目的為個人學習記錄及知識分享。如果有什么不正確、不嚴謹的地方請及時指正&#xff0c;不勝感激。 直達博主&#xff1a;「…

數據結構 | Floyd

參考博文&#xff1a; floyd算法 弗洛伊德算法 多源最短路徑算法_弗洛伊德算法例題-CSDN博客

【文心一言】AI試用寫代碼體會:delphi、php

一、前言&#xff1a; 二、讓【文心一言】編寫一個函數 1. Delphi 語言&#xff08;文心一言的回復&#xff09; 2. php 語言&#xff08;文心一言回復&#xff09; 三、總結 一、前言&#xff1a; 眾所周知&#xff0c;chatGPT是可以自動編寫程序的&#xff0c;甚至可以運…

MyBatis緩存機制流程分析

前言 在進行分析之前&#xff0c;建議快速瀏覽之前寫的理解MyBatis原理、思想&#xff0c;這樣更容易閱讀、理解本篇內容。 驗證一級緩存 MyBatis的緩存有兩級&#xff0c;一級緩存默認開啟&#xff0c;二級緩存需要手動開啟。 重復讀取跑緩存 可以看到&#xff0c;第二次…

OpenAI承認GPT-4變懶,即將發布修復方案提升性能

目錄 1OpenAI承認GPT-4變懶&#xff0c;即將發布修復方案提升性能 2一文秒懂人工智能全球近況 1OpenAI承認GPT-4變懶&#xff0c;即將發布修復方案提升性能 **劃重點:** 1. &#x1f92f; 用戶反饋:GPT-4使用者抱怨OpenAI破壞了體驗&#xff0c;稱模型幾乎“害怕”提供答案。…

Wireshark使用技巧

Wireshark作為網絡數據軟件&#xff0c;功能強大&#xff0c;本專欄介紹僅為冰山一角&#xff0c;僅僅是一個入門級別的介紹&#xff0c;大部分功能還需要在日常工作中進行挖掘。 總結Wireshark軟件的使用技巧如下&#xff1a; 1.合理部署Wireshark的位置&#xff0c;從源頭保障…

基于Java SSM框架實現電影售票系統項目【項目源碼+論文說明】

基于java的SSM框架實現電影售票系統演示 摘要 21世紀的今天&#xff0c;隨著社會的不斷發展與進步&#xff0c;人們對于信息科學化的認識&#xff0c;已由低層次向高層次發展&#xff0c;由原來的感性認識向理性認識提高&#xff0c;管理工作的重要性已逐漸被人們所認識&#…

界面控件DevExpress WPF導航組件,助力升級應用程序用戶體驗!(下)

DevExpress WPF的Side Navigation&#xff08;側邊導航&#xff09;、TreeView、導航面板組件能幫助開發者在WPF項目中添加Windows樣式的資源管理器欄或Outlook NavBar&#xff08;導航欄&#xff09;&#xff0c;DevExpress WPF NavBar和Accordion控件包含了許多開發人員友好的…

rsyslog配置以及原理

rsyslog 日志由程序產生&#xff0c;在內存中產生。通過Rsyslog來將內存中程序產生的日志持久化到硬盤&#xff0c;并且支持udp、tcp等協議來進行不同服務器的日志同步。 /var/log/messages:大多數系統日志信息紀錄在此/var/log/secure&#xff1a;安全和身份認證相關的消息和…

HTTP詳解

1. web 1.1 web相關概念 軟件架構 C /S&#xff1a;客戶端/服務器端 需要安裝客戶端應用 B/S&#xff1a;瀏覽器/服務器端 不需要安裝客戶端應用&#xff0c;對于用戶來說只需要記住域名訪問就可以,高效,客戶端零維護 資源分類 靜態資源&#xff1a;所有用戶訪問后&#x…

數據庫系統原理與實踐 筆記 #12

文章目錄 數據庫系統原理與實踐 筆記 #12事務管理和并發控制與恢復(續)并發控制SQL-92中的并發級別基于鎖的協議基于鎖的協議的隱患鎖的授予封鎖協議兩階段封鎖協議多粒度粒度層次的例子意向鎖類型相容性矩陣多粒度封鎖模式基于時間戳的協議基于時間戳協議的正確性基于有效性檢…

怎樣在PPT中加入音頻文件?記好這4個簡單操作!

“我要制作一個比較專業的PPT來匯報工作成果&#xff0c;想在PPT里加一段音樂&#xff0c;但是不知道應該如何操作&#xff0c;有沒有朋友可以指導一下呢&#xff1f;” PPT作為一種常用的文件形式&#xff0c;很多用戶會將其用于工作匯報&#xff0c;期末總結以及各種演講。在…