Java 自定義異常:如何優雅地處理程序中的“業務病”?

?

🔥「炎碼工坊」技術彈藥已裝填!
點擊關注 → 解鎖工業級干貨【工具實測|項目避坑|源碼燃燒指南】

?

一、從一個真實場景開始:銀行轉賬系統的困境

假設你正在開發一個銀行轉賬系統,當用戶嘗試轉賬時可能出現以下問題:

  1. 轉賬金額為負數(非法輸入)
  2. ?賬戶余額不足(業務規則沖突)
  3. 目標賬戶不存在(數據異常)

如果直接使用if-else處理這些問題,代碼會變成這樣:

//?偽代碼示例(不推薦)
if(amount?<?0)?{System.out.println("錯誤代碼:1001,金額非法");
}?else?if(balance?<?amount)?{System.out.println("錯誤代碼:1002,余額不足");
}?else?if(accountNotExist)?{System.out.println("錯誤代碼:1003,賬戶不存在");
}

這種寫法存在三個致命問題:

  • 錯誤信息分散,維護困難
  • 業務邏輯與錯誤處理混雜
  • 無法區分系統異常與業務異常

二、終極解決方案:自定義異常模式

1. 標準治療方案:創建自定義異常類

//?JDK?1.8+?可運行示例
//?業務異常基類(檢查型異常)
class?BusinessException?extends?Exception?{public?BusinessException(String?message)?{super(message);}
}//?具體異常子類
class?InvalidAmountException?extends?BusinessException?{public?InvalidAmountException(String?message)?{super(message);}
}class?InsufficientBalanceException?extends?BusinessException?{public?InsufficientBalanceException(String?message)?{super(message);}
}class?AccountNotFoundException?extends?BusinessException?{public?AccountNotFoundException(String?message)?{super(message);}
}

2. 異常拋出規范:像醫生診斷一樣精準

public?class?BankService?{//?假設賬戶余額private?double?balance?=?1000;public?void?transfer(double?amount,?String?targetAccount)?throws?BusinessException?{if(amount?<=?0)?{throw?new?InvalidAmountException("轉賬金額必須大于0");}if(balance?<?amount)?{throw?new?InsufficientBalanceException("賬戶余額不足");}if(!"valid_account".equals(targetAccount))?{throw?new?AccountNotFoundException("目標賬戶不存在");}//?實際轉賬邏輯...System.out.println("轉賬成功");}
}

3. 異常處理:統一的異常捕獲

public?class?Main?{public?static?void?main(String[]?args)?{BankService?bank?=?new?BankService();try?{bank.transfer(-100,?"invalid_account");}?catch(InvalidAmountException?e)?{System.err.println("金額異常:"?+?e.getMessage());}?catch(InsufficientBalanceException?e)?{System.err.println("余額不足:"?+?e.getMessage());}?catch(AccountNotFoundException?e)?{System.err.println("賬戶異常:"?+?e.getMessage());}?catch(Exception?e)?{System.err.println("未知異常:"?+?e.getMessage());}}
}

三、不同方案對比:內置異常 vs 自定義異常

方案類型優點缺點適用場景
使用內置異常開發速度快信息模糊,難以區分業務類型簡單腳本或原型開發
自定義異常精準定位問題,業務清晰需要設計類結構正式項目、企業級應用
異常碼+枚舉統一錯誤碼管理需要維護映射關系微服務間通信、API接口
異常鏈模式保留原始異常上下文增加調試復雜度多層架構、框架開發

四、異常處理流程圖解

┌───────────────┐
│???try代碼塊???│
│?嘗試執行業務邏輯?│
└───────┬───────┘│▼
┌───────────────┐
│?是否發生異常?├─否─→?執行正常流程
└───────┬───────┘│是▼
┌───────────────┐
│??匹配異常類型??│
│(按catch順序)?│
└───────┬───────┘│▼
┌───────────────┐
│?執行對應的????│
│?異常處理邏輯??│
└───────┬───────┘│▼
┌───────────────┐
│?執行finally代碼│
│?塊(可選)????│
└───────────────┘

五、最佳實踐指南

  1. 異常分類原則
    • ?RuntimeException?子類:表示編程錯誤(如空指針)
    • Exception?子類:表示業務規則異常(需要強制處理)
  2. 異常信息規范
    //?好的寫法:包含具體上下文
    throw?new?AccountNotFoundException("用戶ID:123456?的賬戶不存在");//?不推薦:模糊描述
    throw?new?AccountNotFoundException("賬戶錯誤");
  3. 資源管理新姿勢(JDK7+)
    //?自動資源管理(ARM)
    try?(FileReader?reader?=?new?FileReader("data.txt"))?{//?使用資源
    }?catch?(IOException?e)?{//?處理異常
    }?//?自動關閉資源,無需finally

六、專有名詞說明表

術語全稱/解釋
Checked異常檢查型異常(Exception子類):必須捕獲或聲明拋出
Unchecked異常非檢查型異常(RuntimeException子類):可不處理
異常鏈異常包裝技術,保留原始異常信息(throw new NewException("msg", cause))
try-with-resourcesJDK7新特性,自動管理資源關閉
業務異常符合業務規則的異常(如余額不足),區別于系統異常(如IO異常)
異常傳播異常從調用棧向上傳遞的過程
finally塊無論是否異常都執行的代碼塊,用于資源清理

七、延伸思考:異常處理的藝術

在大型系統中,建議采用異常分層設計

┌───────────────────────┐
│??API?層???????????????│
│?捕獲全局異常,返回????│
│?標準化錯誤響應????????│
└─────────▲─────────────┘│
┌─────────┴─────────────┐
│??Service?層???????????│
│?拋出業務異常??????????│
└─────────▲─────────────┘│
┌─────────┴─────────────┐
│??DAO?層???????????????│
│?拋出數據訪問異常??????│
└───────────────────────┘

通過合理使用自定義異常,你可以:

  • 提升代碼可讀性:一眼看出業務規則限制
  • ?降低維護成本:異常處理集中管理
  • ?增強系統健壯性:防止異常誤處理
  • 提供調試線索:精確的錯誤定位

記住:優秀的異常設計就像人體的免疫系統——既能及時發現異常,又能精準應對,讓程序在風雨中保持穩定運行。

?

🚧 您已閱讀完全文99%!缺少1%的關鍵操作:
加入「炎碼燃料倉」🚀 獲得:
√ 開源工具紅黑榜
√ 項目落地避坑指南
√ 每周BUG修復進度+1%彩蛋
(溫馨提示:本工坊不打灰工,只燒腦洞🔥)?

?

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

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

相關文章

【JAVA】【Stream流】

1. filter操作 filter()方法用于根據給定的條件過濾列表中的元素&#xff0c;僅保留滿足條件的項。 List<Integer> list Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8);List<Integer> res list.stream().filter(a -> a % 2 0).collect(Collectors.toList());for(I…

四、Redis實現限流

簡介&#xff1a; 限流算法在分布式領域是一個經常被提起的話題&#xff0c;當系統的處理能力有限時&#xff0c;如何阻止計劃外的請求繼續對系統施壓。 系統要限定用戶的某個行為在指定的時間里只能允許發生 N 次&#xff0c;如何使用 Redis 的數據結構來實現這個限流的功能&a…

基于Geotools的兩條道路相交并根據交點形成新路線實戰-以OSM數據為例

目錄 前言 一、需求場景及分解 1、需求場景 2、需求應用 二、需求實現 1、加載路網數據 2、獲取道路信息 3、相交點求解 4、生成新道路 5、結果可視化 三、總結 前言 在當今數字化迅速發展的時代&#xff0c;地理空間數據的處理與分析已成為眾多領域不可或缺的關鍵技…

goland有基礎速通(需要其它編程語言基礎)

tip: 無論是變量、方法還是struct的訪問權限控制都是通過命名控制的&#xff0c;命名的首字母是大寫就相當于java中的public&#xff0c;小寫的話就是private&#xff0c;&#xff08;private只有本包可以訪問&#xff09; 1 go的變量聲明 普通變量 特點&#xff1a; 變量類…

量化面試綠皮書:19. 相關系數

文中內容僅限技術學習與代碼實踐參考&#xff0c;市場存在不確定性&#xff0c;技術分析需謹慎驗證&#xff0c;不構成任何投資建議。 19. 相關系數 假設有三個隨機變量x、y和z。 x與y之間的相關系數為0.8&#xff0c;x與z之間的相關系數也是0.8。 Q: 那么y與z之間的最大相關…

新生活的開啟:從 Trae AI 離開后的三個月

很久沒有寫文章了&#xff0c;想借著入職新公司一個月的機會&#xff0c;和大家嘮嘮嗑。 離職 今年2月份我從字節離職了&#xff0c;結束了四年的經歷&#xff0c;當時離開的核心原因是覺得加班時間太長了&#xff0c;平均每天都要工作15&#xff0c;16個小時&#xff0c;周末…

LLM部署之vllm vs deepspeed

部署大語言模型(如 Qwen/LLaMA 等)時,vLLM 與 DeepSpeed 是當前主流的兩種高性能推理引擎。它們各自專注于不同方向,部署流程也有明顯區別。 vLLM 提供極致吞吐、低延遲的推理服務,適用于在線部署;DeepSpeed 更側重訓練與推理混合優化,支持模型并行,適用于推理 + 微調/…

Git(二):基本操作

文章目錄 Git(二)&#xff1a;基本操作添加文件修改文件版本回退撤銷修改情況一&#xff1a;工作區的代碼還沒有 add情況?&#xff1a;已經 add 但沒有 commit情況三&#xff1a;已經 add 并且也 commit 刪除文件 Git(二)&#xff1a;基本操作 添加文件 首先我們先來學習一個…

nginx + ffmpeg 實現 rtsp視頻實時播放和歷史播放

nginx和ffmpeg 的安裝請參考我的另一篇文章 Nginxrtmpffmpeg搭建視頻轉碼服務_nginx-rtmp-module-master-CSDN博客 目錄 1、整體方案設計如圖 2、nginx下目錄創建和配置文件創建 3、創建視頻流生成腳本 4、修改nginx配置 5、管理界面 (video.html) 6、ffmpeg后臺啟動 …

全國產!瑞芯微 RK3576 ARM 八核 2.2GHz 工業核心板—硬件說明書

前 言 本文為創龍科技 SOM-TL3576 工業核心板硬件說明書,主要提供 SOM-TL3576 工業 核心板的產品功能特點、技術參數、引腳定義等內容,以及為用戶提供相關電路設計指導。 為便于閱讀,下表對文檔出現的部分術語進行解釋;對于廣泛認同釋義的術語,在此不做注釋。 硬件參考…

web3 瀏覽器注入 (如 MetaMask)

以下是關于 瀏覽器注入方式(如 MetaMask) 的完整詳解,包括原理、使用方法、安全注意事項及常見問題解決方案: 1. 核心原理 當用戶安裝 MetaMask 等以太坊錢包擴展時,錢包會向瀏覽器的 window 對象注入一個全局變量 window.ethereum,這個對象遵循 EIP-1193 標準,提供與區…

解密提示詞工程師:AI 時代的新興職業

大家好!在人工智能飛速發展的當下&#xff0c;有一個新興職業正悄然崛起——提示詞工程師。他們雖不如數據科學家般廣為人知&#xff0c;卻在 AI 應用領域發揮著獨特且關鍵的作用。 何為提示詞工程師&#xff1f; 提示詞工程師專注于設計和優化與 AI 模型進行交互的提示詞&…

linux 下 jenkins 構建 uniapp node-sass 報錯

背景: jenkins 中構建 uniapp 應用 配置: 1. 將windows HbuilderX 插件目錄下的 uniapp-cli 文件夾復制到 服務器 /var/jenkins_home/uniapp-cli 2. jenkins 構建步驟增加 執行 shell ,內容如下 echo ">> 構建中..."# 打包前端 export LANGen_US.UTF-8…

QT常見問題(1)

QT常見問題&#xff08;1&#xff09; 1.問題描述 Qt在編譯器中直接運行沒有任何問題&#xff0c;但是進入exe生成目錄直接雙擊運行就報錯&#xff1a;文件無法定位程序輸入點_zn10qarraydata10deallocateepsyy于動態鏈接庫。 2.問題原因 這個錯誤通常是由于程序運行時找不…

『大模型筆記』第2篇:并發請求中的 Prefill 與 Decode:優化大語言模型性能

『大模型筆記』并發請求中的 Prefill 與 Decode:優化大語言模型性能 文章目錄 一. Token 生成的兩個階段:Prefill 和 Decode1.1. 指標分析1.2. 資源利用率分析二. 并發處理機制2.1. 靜態批處理 vs 持續批處理(Static Batching vs. Continuous Batching)2.2. Prefill 優先策略…

JVM(7)——詳解標記-整理算法

核心思想 標記-整理算法同樣分為兩個主要階段&#xff0c;但第二個階段有所不同&#xff1a; 標記階段&#xff1a; 與標記-清除算法完全一致。遍歷所有可達對象&#xff08;從 GC Roots 開始&#xff09;&#xff0c;標記它們為“存活”。 整理階段&#xff1a; 不再簡單地清…

進程虛擬地址空間

1. 程序地址空間回顧 我們在學習語言層面時&#xff0c;會了解到這樣的空間布局圖&#xff0c;我們先對他進行分區了解&#xff1a; 如果以靜態static修飾的變量就會當成已初始化全局變量來看待&#xff0c;存放在已初始化數據區和未初始化數據區之前。 如果不用static修飾test…

C語言學習day17-----位運算

目錄 1.位運算 1.1基礎知識 1.1.1定義 1.1.2用途 1.1.3軟件控制硬件 1.2運算符 1.2.1與 & 1.2.2或 | 1.2.3非 ~ 1.2.4異或 ^ 1.2.5左移 << 1.2.6右移 >> 1.2.7代碼實現 1.2.8置0 1.2.9置1 1.2.10不借助第三方變量&#xff0c;實現兩個數的交換…

【linux】簡單的shell腳本練習

簡單易學 解釋性語言&#xff0c;不需要編譯即可執行 對于一個合格的系統管理員來說&#xff0c;學習和掌握Shell編程是非常重要的&#xff0c;通過shell程序&#xff0c;可以在很大程度上簡化日常的維護工作&#xff0c;使得管理員從簡單的重復勞動中解脫出來 用戶輸入任意兩…

機構運動分析系統開發(Python實現)

機構運動分析系統開發(Python實現) 一、引言 機構運動分析是機械工程的核心內容,涉及位置、速度和加速度分析。本系統基于Python開發,實現了平面連桿機構的完整運動學分析,包含數學建模、數值計算和可視化功能。 二、系統架構設計 #mermaid-svg-bT8TPKQ98UU9ERet {font…