Java異常處理全解析:從基礎到自定義

目錄

  • 🚀前言
  • 🤔異常的定義與分類
    • 💯運行時異常
    • 💯編譯時異常
    • 💯異常的基本處理
  • 🌟異常的作用
  • 🐧自定義異常
    • 💯自定義運行時異常
    • 💯自定義編譯時異常
  • ??異常的處理方案
    • 💯方案一:異常捕獲與用戶友好提示
    • 💯方案二:異常捕獲與自動修復

🚀前言

在這里插入圖片描述

大家好!我是 EnigmaCoder
本文介紹java的異常部分,從基礎到自定義,最后到處理方案進行全解析。

🤔異常的定義與分類

定義Java 中的異常是程序運行時發生的錯誤或意外情況,是Throwable類的子類,用于封裝程序執行過程中出現的不正常事件,可通過異常處理機制進行捕獲和處理,分為可處理的Exception(包括受檢查異常和運行時異常)和不可處理的Error(系統級錯誤)。

異常的分類

Java 異常體系基于Throwable類,主要分為兩大類:

  • Error:系統級錯誤(如內存溢出OutOfMemoryError),程序無法處理,也就是說系統一旦出現問題,sun公司會把這些問題封裝成Error對象給出來。
  • Exception:指可被程序捕獲和處理的異常,我們程序員通常會用Exception以及它的孩子來封裝程序出現的問題,其進一步分為:
    • 運行時異常(RuntimeException):RuntimeException及其子類,編譯階段不會出現錯誤提示,運行時出現的異常。(如:數組索引越界異常)
    • 編譯時異常(Checked Exception):編譯階段會出現錯誤提示。(如:日期解析異常)

💯運行時異常

特點:編譯階段不會報錯,運行時出現的異常,繼承自RuntimeException類。

示例:

public class Text {public static void main(String[] args) {int []arr={1,2,3,4,5};System.out.println(arr[5]);}
}

這是一段數組越界的的代碼,編譯時沒有報錯,運行時就會出現以下報錯:

在這里插入圖片描述

💯編譯時異常

public class Text {public static void main(String[] args) {show();}public static void show(){System.out.println("==程序開始==");String str="2025-01-01 00:00:00";SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date date=sdf.parse(str);System.out.println(date);System.out.println("==程序結束==");}
}

報錯信息如下:
在這里插入圖片描述
在這里插入圖片描述

💯異常的基本處理

  • 拋出異常(throws

    在方法上使用throws關鍵字,可以將方法內部出現的異常拋出去給調用者處理。

格式如下:

方法  throws 異常1,異常2,異常3 ...{...
}
  • 捕獲異常(try...catch

    直接捕獲程序出現的異常。

格式如下:

try{//監視可能出現異常的代碼
}catch (異常類型1 變量){//處理異常
}catch (異常類型2 變量){//處理異常
}...

🌟異常的作用

  • 作用1:異常是用來定位程序bug的關鍵信息

異常是程序運行過程中發生錯誤或異常情況時拋出的信號。它包含了豐富的調試信息,可以幫助開發者快速定位和修復問題。具體來說:

  1. 異常類型:指明錯誤的性質,如NullPointerExceptionArrayIndexOutOfBoundsException等。
  2. 異常信息:描述錯誤的具體原因,如"Index 5 out of bounds for length 3"。
  3. 堆棧跟蹤:顯示異常發生時的調用鏈,幫助定位問題發生的具體位置。
try {int[] arr = new int[3];System.out.println(arr[5]);
} catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();// 輸出:// java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3//     at Main.main(Main.java:5)
}

通過分析異常信息,開發者可以快速定位到數組越界的問題發生在Main.java文件的第5行。

  • 作用2:可以作為方法內部的一種特殊返回值以便通知上層調用者,方法的執行問題

在方法設計中,異常機制提供了一種優雅的錯誤處理方式,相比傳統的錯誤碼返回具有以下優勢:

  1. 強制處理:調用者必須處理或繼續拋出檢查型異常(Checked Exception)。
  2. 信息豐富:可以攜帶詳細的錯誤描述和上下文信息。
  3. 代碼解耦:將正常業務邏輯與錯誤處理邏輯分離,提高代碼可讀性。

應用場景示例:

public void transfer(Account from, Account to, double amount) throws InsufficientBalanceException {if (from.getBalance() < amount) {throw new InsufficientBalanceException("賬戶余額不足,當前余額:" + from.getBalance());}// 執行轉賬邏輯
}// 調用方法
try {transfer(accountA, accountB, 1000);
} catch (InsufficientBalanceException e) {System.out.println("轉賬失敗:" + e.getMessage());// 輸出:轉賬失敗:賬戶余額不足,當前余額:500.0
}

通過拋出異常,transfer方法清晰地表達了業務約束,調用方可以針對性地處理特定錯誤情況,而不是依賴模糊的錯誤碼或布爾返回值。

🐧自定義異常

java無法為這個世界上全部的問題都提供異常類來代表,如果企業自己的某種問題,想通過異常來表示,以便用異常來管理該問題,那就需要自己來定義異常類了。

💯自定義運行時異常

  • 定義一個異常類繼承RuntimeException
public class CustomRuntimeException extends RuntimeException {// 類體
}
  • 重寫構造器
public class CustomRuntimeException extends RuntimeException {// 無參構造器public CustomRuntimeException() {super();}// 帶消息的構造器public CustomRuntimeException(String message) {super(message);}// 帶消息和原因的構造器public CustomRuntimeException(String message, Throwable cause) {super(message, cause);}// 帶原因的構造器public CustomRuntimeException(Throwable cause) {super(cause);}
}
  • 通過throw new 異常類(xxx)來創建異常對象并拋出。
public void someMethod(int value) {if (value < 0) {throw new CustomRuntimeException("Value cannot be negative");}// 其他邏輯
}

特點:編譯階段不報錯,運行時才可能出現。

💯自定義編譯時異常

  • 定義一個異常類繼承Exception
public class CustomCompileException extends Exception {// 異常類的具體實現
}
  • 重寫構造器。
public class CustomCompileException extends Exception {// 無參構造器public CustomCompileException() {super();}// 帶有錯誤信息的構造器public CustomCompileException(String message) {super(message);}// 帶有錯誤信息和原因的構造器public CustomCompileException(String message, Throwable cause) {super(message, cause);}// 僅帶有原因的構造器public CustomCompileException(Throwable cause) {super(cause);}
}
  • 通過throw new 異常類(xxx)創建異常對象并拋出。
public void validateInput(String input) throws CustomCompileException {if (input == null || input.isEmpty()) {throw new CustomCompileException("輸入不能為空");}// 其他邏輯
}

特點:編譯階段就報錯,提醒十分激進。

??異常的處理方案

💯方案一:異常捕獲與用戶友好提示

底層異常層層往上拋出,最外層捕獲異常,記錄下異常信息,并響應適合用戶觀看的信息進行提示。

處理流程

  • 異常拋出:在底層代碼中,當檢測到異常情況時,使用 throw 關鍵字拋出異常對象。例如,在數據庫操作中,如果查詢失敗,可以拋出 SQLException

  • 異常傳遞:異常會沿著調用棧向上傳遞,直到被捕獲。中間層代碼可以選擇不處理異常,繼續向上拋出。例如,在服務層捕獲SQLException 后,可以將其包裝為自定義的業務異常 BusinessException 并繼續拋出。

  • 最外層捕獲:在應用的最外層(如控制器層或主函數)使用 try-catch塊捕獲所有異常。例如,在 Spring MVC的控制器中,可以使用 @ExceptionHandler 注解來統一處理異常。

  • 記錄日志:捕獲異常后,使用日志框架(如 Log4jSLF4J)記錄異常的詳細信息,包括異常類型、堆棧軌跡、發生時間等。這有助于后續的問題排查和分析。

  • 用戶提示:根據異常類型,生成適合用戶觀看的提示信息。例如,對于網絡超時異常,可以提示“網絡連接不穩定,請稍后重試”;對于權限不足異常,可以提示“您沒有權限執行此操作”。

示例代碼

try {// 業務邏輯代碼
} catch (BusinessException e) {logger.error("業務異常: ", e);return new Response("操作失敗,請檢查輸入是否正確");
} catch (Exception e) {logger.error("系統異常: ", e);return new Response("系統繁忙,請稍后重試");
}

應用場景

  • Web 應用中的全局異常處理
  • 微服務架構中的服務間調用異常處理
  • 桌面應用程序中的用戶操作異常處理

💯方案二:異常捕獲與自動修復

最外層捕獲異常后,嘗試重新修復。

處理流程

  • 異常捕獲:在最外層代碼中捕獲異常,與方案一類似。

  • 異常分析:根據異常類型和上下文信息,判斷是否可以進行自動修復。例如,對于網絡連接異常,可以嘗試重新連接;對于文件讀取異常,可以嘗試從備份文件讀取。

  • 修復嘗試:

    • 重試機制:對于暫時性異常(如網絡抖動),可以設置重試次數和間隔時間,多次嘗試執行操作。
    • 備用方案:對于無法直接修復的異常,可以切換到備用方案。例如,主數據庫不可用時,切換到備用數據庫。
    • 資源清理:在修復過程中,可能需要釋放已占用的資源,如關閉文件句柄、釋放數據庫連接等。
  • 結果處理:

    • 如果修復成功,繼續正常執行后續邏輯。
    • 如果修復失敗,記錄日志并按照方案一的方式向用戶提示錯誤信息。

示例代碼

int retryCount = 3;
while (retryCount > 0) {try {// 可能失敗的操作performOperation();break; // 成功則退出循環} catch (NetworkException e) {retryCount--;if (retryCount == 0) {logger.error("網絡連接失敗,重試次數用盡");return new Response("網絡連接失敗,請檢查網絡設置");}Thread.sleep(1000); // 等待1秒后重試}
}

應用場景

  • 分布式系統中的容錯處理
  • 實時數據處理系統的故障恢復
  • 自動化運維系統中的錯誤自愈

注意事項

  • 自動修復可能會掩蓋潛在的系統問題,應謹慎使用
  • 需要設置合理的重試次數和間隔時間,避免無限重試
  • 對于關鍵業務操作,建議在自動修復后仍進行人工確認

通過以上兩種方案,可以有效地處理系統中的異常情況,提高系統的穩定性和用戶體驗。具體選擇哪種方案,需要根據業務場景和異常類型來決定。

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

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

相關文章

Redisson分布式集合原理及應用

Redisson是一個用于Redis的Java客戶端&#xff0c;它簡化了復雜的數據結構和分布式服務的使用。 適用場景對比 數據結構適用場景優點RList消息隊列、任務隊列、歷史記錄分布式共享、阻塞操作、分頁查詢RMap緩存、配置中心、鍵值關聯數據支持鍵值對、分布式事務、TTLRSet去重集…

打破次元壁,VR 氣象站開啟氣象學習新姿勢?

在教育領域&#xff0c;VR 氣象站同樣發揮著巨大的作用&#xff0c;為氣象教學帶來了全新的模式&#xff0c;打破了傳統教學的次元壁&#xff0c;讓學生們以全新的姿勢學習氣象知識。? 在傳統的氣象教學中&#xff0c;學生們主要通過課本、圖片和老師的講解來學習氣象知識。這…

k8s面試題-ingress

場景&#xff1a;我通過deployment更新pod&#xff0c;ingress是怎么把新的請求流量發送到我新的pod的&#xff1f;是怎么監控到我更新的pod的&#xff1f; 在 Kubernetes 中&#xff0c;Ingress 是一種 API 對象&#xff0c;用于管理外部訪問到集群內服務的 HTTP 和 HTTPS 路…

RHCE 練習三:架設一臺 NFS 服務器

一、題目要求 1、開放 /nfs/shared 目錄&#xff0c;供所有用戶查詢資料 2、開放 /nfs/upload 目錄&#xff0c;為 192.168.xxx.0/24 網段主機可以上傳目錄&#xff0c;并將所有用戶及所屬的組映射為 nfs-upload,其 UID 和 GID 均為 210 3.將 /home/tom 目錄僅共享給 192.16…

【動態導通電阻】GaN HEMT動態導通電阻的精確測量

2023 年 7 月,瑞士洛桑聯邦理工學院的 Hongkeng Zhu 和 Elison Matioli 在《IEEE Transactions on Power Electronics》期刊發表了題為《Accurate Measurement of Dynamic ON-Resistance in GaN Transistors at Steady-State》的文章,基于提出的穩態測量方法,研究了氮化鎵(…

AI 制作游戲美術素材流程分享(程序員方向粗糙版)

AI 制作游戲美術素材分享(程序員方向粗糙版) 視頻講解: 抖音:https://www.douyin.com/user/self?from_tab_namemain&modal_id7505691614690561295&showTabpost Bilibili: https://www.bilibili.com/video/BV1ojJGzZEve/ 寫在最前面: 本方法比較粗糙,只對對美術風…

Java求職面試:互聯網大廠技術棧深度解析

文章簡述 在這篇文章中&#xff0c;我們將通過一個模擬的面試場景&#xff0c;帶你深入了解Java求職面試中可能會遇到的技術棧問題。通過這個故事&#xff0c;你可以學習到相關技術點的具體應用場景和面試技巧。 正文 場景&#xff1a;某互聯網大廠的面試現場 面試官&#…

學習日記-day11-5.20

完成目標&#xff1a; comment.java package com.zcr.pojo; import org.hibernate.annotations.GenericGenerator;import javax.persistence.*; //JPA操作表中數據&#xff0c;可以將對應的實體類映射到一張表上Entity(name "t_comment")//表示當前的實體類與哪張表…

機器學習第十九講:交叉驗證 → 用五次模擬考試驗證真實水平

機器學習第十九講&#xff1a;交叉驗證 → 用五次模擬考試驗證真實水平 資料取自《零基礎學機器學習》。 查看總目錄&#xff1a;學習大綱 關于DeepSeek本地部署指南可以看下我之前寫的文章&#xff1a;DeepSeek R1本地與線上滿血版部署&#xff1a;超詳細手把手指南 交叉驗證…

Linux面試題集合(6)

創建多級目錄或者同級目錄 mkdir -p 文件名/文件名/文件名 mkdir -p 文件名 文件名 文件名 Linux創建一個文件 touch 文件名 DOS命令創建文件 echo 內容>文件名&#xff08;創建一個有內容的文件&#xff09; echo >文件名&#xff08;創建一個沒有內容的文件&#xff09…

Vue百日學習計劃Day46-48天詳細計劃-Gemini版

Day 46: <KeepAlive> - 組件緩存與優化 (~3 小時) 本日目標: 理解 <KeepAlive> 的作用&#xff0c;學會如何使用它來緩存組件實例&#xff0c;從而優化應用性能和用戶體驗。所需資源: Vue 3 官方文檔 (<KeepAlive>): https://cn.vuejs.org/guide/built-ins/…

SpringBean模塊(三)具有生命周期管理能力的類(1)AutowireCapableBeanFactory

一、介紹 1、簡介 AutowireCapableBeanFactory 是 Spring 框架中的一個接口&#xff0c;位于 org.springframework.beans.factory 包下&#xff0c;它提供了更底層的 Bean 實例化、依賴注入和生命周期管理能力&#xff0c;即使這些 Bean 沒有通過常規的 Component 或 XML 注冊…

Service Mesh

目錄 一、Service Mesh 的核心特點 二、Service Mesh 的典型架構 1. Sidecar 模式 2. 控制平面與數據平面分離 三、Service Mesh 解決的核心問題 四、典型應用場景 五、主流 Service Mesh 框架對比 六、挑戰與局限性 七、未來趨勢 總結 Istio 一、Istio 核心組件與…

黑馬Java基礎筆記-13常用查找算法

查找算法 基本查找(也叫順序查找&#xff0c;線性查找) 二分查找&#xff08;需要有序數據&#xff09; public static int binarySearch(int[] arr, int number){//1.定義兩個變量記錄要查找的范圍int min 0;int max arr.length - 1;//2.利用循環不斷的去找要查找的數據wh…

Go 語言 vs C+Lua(Skynet)游戲服務器方案對比分析

為啥挑這兩個呢&#xff1f;因為兩種技術分別對應CSP模型和Actor模型&#xff0c;都是經過時間檢驗的成熟且可靠的并發模型&#xff0c;問了很多地方&#xff0c;經過gpt整理得出如下報告。 從開發效率、運行性能、熱更新擴展、云部署與水平擴展能力、多類型游戲支持等五個維度…

LeetCode 925. 長按鍵入 java題解

雙指針。不會寫。 https://leetcode.cn/problems/long-pressed-name/description/ class Solution {public boolean isLongPressedName(String name, String typed) {int len1name.length();int len2typed.length();int i0,j0;while(i<len1&&j<len2){if(name.ch…

如何使用通義靈碼提高前端開發效率

工欲善其事&#xff0c;必先利其器。對于前端開發而言&#xff0c;使用VSCode已經能夠極大地提高前端的開發效率了。但有了AI加持后&#xff0c;前端開發的效率又更上一層樓了&#xff01; 本文采用的AI是通義靈碼插件提供的通義千問大模型&#xff0c;是目前AI性能榜第一梯隊…

【小明劍魔視頻Viggle AI模仿的核心算法組成】

Viggle AI 作為一款先進的生成式視頻AI工具&#xff0c;其核心技術棧融合了多項前沿算法。以下是深度解析其核心算法架構及實現原理&#xff1a; 一、核心算法組成 1. 運動控制生成&#xff08;Motion Control Generation&#xff09; 算法框架&#xff1a;基于擴散模型&…

解決Power BI Desktop導入Excel數據第一行不是列標題問題

選中第一行不是列標題的表→鼠標右鍵→選擇編輯查詢→進入Power Query界面→點擊“將第一行用作標題”→點擊左邊的“關閉并應用” 第一行就提升為標題了

對 Lambda 架構問題的深入理解

感謝 GPT&#xff0c;對很多問題的理解有機會更深。 大家攻擊 Lambda 架構&#xff0c;常說的一個點就是 “實時離線指標存在差異”。“實時離線指標存在差異”&#xff0c;是一個真實困擾運營方的問題嗎&#xff1f; 答案&#xff1a;是的&#xff0c;這是一個真實生活中的痛…