零基礎學Java第二十二講---異常(2)

????????續接上一講

目錄

一、異常的處理(續)

1、異常的捕獲-try-catch捕獲并處理異常

1.1關于異常的處理方式

2、finally

3、異常的處理流程

二、自定義異常類

1、實現自定義異常類


一、異常的處理(續)

1、異常的捕獲-try-catch捕獲并處理異常

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

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

例:讀取配置文件,如果配置文件名字不是指定名字,拋出異常,調用者進行異常處理

 public class Config {File file;public void openConfig(String filename) throws FileNotFoundException{if(!filename.equals("config.ini")){throw new FileNotFoundException("配置?件名字不對");}// 打開?件 }public void readConfig(){}public static void main(String[] args) {Config config = new Config();try {config.openConfig("config.txt");System.out.println("?件打開成功");} catch (IOException e) {// 異常的處理?式//System.out.println(e.getMessage());   // 只打印異常信息 //System.out.println(e);                // 打印異常類型:異常信息             e.printStackTrace();                    // 打印信息最全?}// ?旦異常被捕獲處理了,此處的代碼會執? System.out.println("異常如果被處理了,這?的代碼也可以執?");}}

1.1關于異常的處理方式

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

(1)對于比較嚴重的問題(如算錢),應該直接讓程序崩潰,減小損失

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

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

????????在我們當前的代碼中采取的是經過簡化的第?種方式.我們記錄的錯誤日志是出現異常的方法調用信息,能很快速的讓我們找到出現異常的位置.以后在實際工作中我們會采取更完備的方式來記錄異常信息

#注:

(1)try塊內拋出異常位置之后的代碼將不會被執行

(2)如果拋出異常類型與catch時異常類型不匹配,即異常不會被成功捕獲,也就不會被處理,繼續往外拋,直到JVM收到后中斷程序----異常是按照類型來捕獲的

 public static void main(String[] args) {try {int[] array = {1,2,3};System.out.println(array[3]);  // 此處會拋出數組越界異常 }catch (NullPointerException e){   // 捕獲時候捕獲的是空指針異常--真正的異常?法被捕獲到 e.printStackTrace();}System.out.println("后續代碼");}Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3at day20210917.ArrayOperator.main(ArrayOperator.java:24)

(3)try中可能會拋出多個不同的異常對象,則必須用多個catch來捕獲----即多種異常,多次捕獲

 public static void main(String[] args) {int[] array = {1, 2, 3};try {System.out.println("before");// array  = null;System.out.println(array [100]);System.out.println("after");} catch (ArrayIndexOutOfBoundsException e) {System.out.println("這是個數組下標越界異常");e.printStackTrace();} catch (NullPointerException e) {System.out.println("這是個空指針異常");e.printStackTrace();}System.out.println("after try catch");}

????????如果多個異常完全相同,也可以這樣寫:

 catch (ArrayIndexOutOfBoundsException | NullPointerException e) {...}

????????如果異常之間具有父子關系,?定是子類異常在前catch,父類異常在后catch,否則語法錯誤:

 public static void main(String[] args) {int[] arr = {1, 2, 3};try {System.out.println("before");arr = null;System.out.println(arr[100]);System.out.println("after");} catch (Exception e) {   // Exception可以捕獲到所有異常 e.printStackTrace();}catch (NullPointerException e){  // 永遠都捕獲執?到 e.printStackTrace();}System.out.println("after try catch");}Error:(33, 10) java: 已捕獲到異常錯誤java.lang.NullPointerException

(4)可以通過?個catch捕獲所有的異常,即多個異常,?次捕獲(不推薦)

 public static void main(String[] args) {int[] arr = {1, 2, 3};try {System.out.println("before");arr = null;System.out.println(arr[100]);System.out.println("after");} catch (Exception e) {e.printStackTrace();}System.out.println("after try catch");}

????????由于Exception類是所有異常類的父類.因此可以用這個類型表示捕捉所有異常.

#注:catch進行類型匹配的時候,不光會匹配相同類型的異常對象,也會捕捉目標異常類型的子類對 象

2、finally

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

語法格式:
try{// 可能會發?異常的代碼 
}catch(異常類型 e){// 對捕獲到的異常進?處理 
}finally{// 此處的語句?論是否發?異常,都會被執?到
}// 如果沒有拋出異常,或者異常被捕獲處理了,這?的代碼也會執?
public static void main(String[] args) {try{int[] array = {1,2,3};array [100] = 10;array [0] = 10;}catch (ArrayIndexOutOfBoundsException e){System.out.println(e);}finally {System.out.println("finally中的代碼?定會執?");}System.out.println("如果沒有拋出異常,或者異常被處理了,try-catch后的代碼也會執?");}

#注:finally中的代碼?定會執行的,?般在finally中進行?些資源清理的掃尾工作,如果異常被捕獲,那么將不會繼續執行后續的內容,而是直接走完當前捕獲異常的catch后直接走finally(除了finally其他的都不執行)

????????finally 執行的時機是在方法返回之前(try或者catch中如果有return會在這個return之前執行 finally). 但是如果finally 中也存在return語句,那么就會執行finally中的return,從而不會執行到try 中原有的return.

?????????般我們不建議在finally中寫return(會被編譯器當做?個警告)

3、異常的處理流程

關于“調用棧”:

????????方法之間是存在相互調用關系的,這種調用關系我們可以"調用棧"來描述.在JVM中有?塊內存空間稱為"虛擬機棧",專門存儲方法之間的調用關系.當代碼中出現異常的時候,我們就可以使用 e.printStackTrace(); 的方式查看出現異常代碼的調用棧.

????????如果本方法中沒有合適的處理異常的方式,就會沿著調用棧向上傳遞

 public static void main(String[] args) {try {func();} catch (ArrayIndexOutOfBoundsException e) {e.printStackTrace();}System.out.println("after try catch");}public static void func() {int[] array = {1, 2, 3};System.out.println(array[100]);}//結果java.lang.ArrayIndexOutOfBoundsException: Index 100 out of bounds for length 3at LibrarySystem.func(LibrarySystem.java:107)at LibrarySystem.main(LibrarySystem.java:98)after try catch

????????如果向上?直傳遞都沒有合適的方法處理異常,最終就會交給JVM處理,程序就會異常終止(和我們最開始未使用trycatch時是?樣的)

異常處理流程總結:

(1)程序先執行try中的代碼

(2)如果try中的代碼出現異常,就會結束try中的代碼,看和catch中的異常類型是否匹配

(3)如果找到匹配的異常類型,就會執行catch中的代碼

(4)如果沒有找到匹配的異常類型,就會將異常向上傳遞到上層調用者

(5)無論是否找到匹配的異常類型,finally中的代碼都會被執行到(在該方法結束之前執行)

(6)如果上層調用者也沒有處理的了異常,就繼續向上傳遞

(7)?直到main方法也沒有合適的代碼處理異常,就會交給JVM來進行處理,此時程序就會異常終止

二、自定義異常類

????????Java 中雖然已經內置了豐富的異常類,但是并不能完全表示實際開發中所遇到的?些異常,此時就需要維護符合我們實際情況的異常結構

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

 public class LogIn {private String userName = "admin";private String password = "123456";public void loginInfo(String userName, String password) {if (!this.userName.equals(userName)) {System.out.println("??名錯誤!");return;}if (!this.password.equals(password)) {System.out.println("密碼錯誤!");return;}System.out.println("登陸成功");}public static void main(String[] args) {LogIn logIn = new LogIn();logIn.loginInfo("admin111", "123456");}}

????????此時我們在處理用戶名密碼錯誤的時候可能就需要拋出兩種異常.我們可以基于已有的異常類進行擴展 (繼承),創建和我們業務相關的異常類

1、實現自定義異常類

具體方式:

(1)自定義異常類,然后繼承自Exception或者RunTimeException

(2)實現?個帶有String類型參數的構造方法,參數含義:出現異常的原因

 class UserNameException extends Exception {public UserNameException(String message) {super(message);}}class PasswordException extends Exception {public PasswordException(String message) {super(message);}}

此時我們的LogIn代碼可以改成:

public class LogIn {private String userName = "admin";private String password = "123456";public void loginInfo(String userName, String password)  throws UserNameException,PasswordException{if (!this.userName.equals(userName)) {throw new UserNameException("用戶名錯誤!");}if (!this.password.equals(password)) {throw new PasswordException("用戶名錯誤!");}System.out.println("登陸成功");}public static void main(String[] args) {try {LogIn login = new LogIn();login.loginInfo("admin", "123456");} catch (UserNameException e) {e.printStackTrace();} catch (PasswordException e) {e.printStackTrace();}}}

#注:

(1)自定義異常通常會繼承自Exception或者RuntimeException

(2)繼承自Exception的異常默認是受查異常

(3)繼承自RuntimeException的異常默認是非受查異常

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

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

相關文章

自建開發工具IDE(一)之拖找排版—仙盟創夢IDE

自建拖拽布局排版在 IDE 中的優勢及初學者開發指南在軟件開發領域,用戶界面(UI)的設計至關重要。自建拖拽布局排版功能為集成開發環境(IDE)帶來了諸多便利,尤其對于初學者而言,是踏入開發領域的…

GitHub Copilot - GitHub 推出的AI編程助手

本文轉載自:GitHub Copilot - GitHub 推出的AI編程助手 - Hello123工具導航。 ** 一、GitHub Copilot 核心定位 GitHub Copilot 是由 GitHub 與 OpenAI 聯合開發的 AI 編程助手,基于先進大語言模型實現代碼實時補全、錯誤檢測及文檔生成,顯…

基于截止至 2025 年 6 月 4 日,在 App Store 上進行交易的設備數據統計,iOS/iPadOS 各版本在所有設備中所占比例詳情

iOS 和 iPadOS 使用情況 基于截止至 2025 年 6 月 4 日,在 App Store 上進行交易的設備數據統計。 iPhone 在過去四年推出的設備中,iOS 18 的普及率達 88。 88% iOS 188% iOS 174% 較早版本 所有的設備中,iOS 18 的普及率達 82。 82% iOS 189…

云計算-k8s實戰指南:從 ServiceMesh 服務網格、流量管理、limitrange管理、親和性、環境變量到RBAC管理全流程

介紹 本文是一份 Kubernetes 與 ServiceMesh 實戰操作指南,涵蓋多個核心功能配置場景。從 Bookinfo 應用部署入手,詳細演示了通過 Istio 創建 Ingress Gateway 實現外部訪問,以及基于用戶身份、請求路徑的服務網格路由規則配置,同時為應用微服務設置了默認目標規則。 還包…

Vue 3項目中的路由管理和狀態管理系統

核心概念理解 1. 整體架構關系 這兩個文件構成了Vue應用的導航系統和狀態管理系統: Router(路由):控制頁面跳轉和URL變化Store(狀態):管理全局數據和用戶狀態兩者協同工作實現權限控制 2. 數據流…

Linux Capability 解析

文章目錄1. 權限模型演進背景2. Capability核心原理2.1 能力單元分類2.2 進程三集合2.3 文件系統屬性3. 完整能力單元表4. 高級應用場景4.1 能力邊界控制4.2 編程控制4.3 容器安全5. 安全實踐建議6. 潛在風險提示 1. 權限模型演進背景 在傳統UNIX權限模型中,采用二進…

vue 監聽 sessionStorage 值的變化

<template><div class"specific-storage-watcher"><h3>僅監聽 userId 變化</h3><p>當前 userId: {{ currentUserId }}</p><p v-if"changeRecord">最近變化: {{ changeRecord }}</p><button click"…

IDEA:控制臺中文亂碼

目錄一、設置字符編碼為 UTF-8一、設置字符編碼為 UTF-8 點擊菜單 File -> settings -> Eitor -> File Encodings , 將字符全局編碼、項目編碼、配置文件編碼統一設置為UTF-8, 然后點擊 Apply 應用設置&#xff0c;點擊 OK 關閉對話框:

[Sql Server]特殊數值計算

任務一&#xff1a;求下方的Num列的中值:參考代碼:use Test go SELECT DISTINCTPERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY Num) over()AS MedianSalary FROM MedianTest;任務二: 下方表中,每個選手有多個評委打分&#xff0c;求每個選手的評委打分中值。參考代碼:use Tes…

01-Docker概述

Docker 的主要目標是:Build, Ship and Run Any App, Anywhere,也就是通過對應用組件的封裝、分發、部署、運行等生命周期的管理,使用戶的 APP 及其運行環境能做到一次鏡像,處處運行。 Docker 運行速度快的原因: 由于 Docker 不需要 Hypervisor(虛擬機)實現硬件資源虛擬化…

Laravel中如何使用php-casbin

一、&#x1f680; 安裝和配置 1. 安裝包 composer require casbin/laravel-authz2. 發布配置文件 php artisan vendor:publish這會生成兩個重要文件&#xff1a; config/lauthz.php - 主配置文件config/lauthz-rbac-model.conf - RBAC 模型配置文件 3. 運行數據庫遷移 php…

算法題打卡力扣第4題:尋找兩個正序數組的中位數(hard))

題目描述 提示&#xff1a; nums1.length m nums2.length n 0 < m < 1000 0 < n < 1000 1 < m n < 2000 -106 < nums1[i], nums2[i] < 106 解答思路 我的想法是先歸并排序再直接返回下標中位數 代碼 double findMedianSortedArrays(int* nums1,…

無人機抗噪模塊技術概述!

一、 技術要點1. 傳感器數據融合與濾波&#xff08;解決感知噪聲&#xff09;核心思想&#xff1a;單一傳感器易受干擾且不全面&#xff0c;通過融合多種傳感器&#xff08;IMU慣性測量單元、GPS、氣壓計、磁力計、視覺傳感器、激光雷達等&#xff09;的數據&#xff0c;利用算…

Horse3D游戲引擎研發筆記(六):在QtOpenGL環境下,仿Unity的材質管理Shader繪制四邊形

在上一篇筆記中&#xff0c;我們已經實現了基于QtOpenGL的BufferGeometry管理VAO和EBO繪制四邊形的功能。這一次&#xff0c;我們將深入探討材質管理系統的實現&#xff0c;包括Shader的加載與編譯、材質的創建與使用&#xff0c;以及如何通過材質系統繪制帶有自定義Shader效果…

MySQL-分庫分表(Mycat)

目錄 1.介紹? 概述 拆分策略 垂直拆分? 水平拆分? 實現技術? shardingJDBC: MyCat: 2.Mycat概述 環境準備? 分片配置 schema.xml? server.xml 啟動服務? 分片測試? 3.MyCat配置 schema.xml? schema標簽 datanode標簽 ?datahost標簽? rule.xml …

Dubbo 的 Java 項目間調用的完整示例

1. 項目結構假設項目分為三個模塊&#xff1a;api&#xff1a;定義服務接口provider&#xff1a;服務提供者consumer&#xff1a;服務消費者2. 依賴配置在 pom.xml 中添加 Dubbo 和注冊中心&#xff08;如 Nacos&#xff09;的依賴&#xff1a;<dependency><groupId&g…

Python進行中文分詞

1. jieba庫概述 jieba&#xff08;“結巴”&#xff09;是Python中最流行的中文分詞庫&#xff0c;采用基于前綴詞典實現的高效分詞算法&#xff0c;支持多種分詞模式&#xff0c;是中文自然語言處理(NLP)的基礎工具。 核心特性 精確模式&#xff1a;試圖將句子最精確地切開&am…

JavaScript 性能優化實戰:從原理到落地的完整指南

一、引言&#xff1a;為什么 JavaScript 性能優化至關重要&#xff1f;性能與用戶體驗的強關聯數據支撐&#xff1a;加載延遲每增加 1 秒&#xff0c;用戶轉化率下降 7%&#xff08;來自 Google 研究&#xff09;核心痛點&#xff1a;現代 Web 應用中 JS 代碼體積膨脹、運行時卡…

前端自動化部署

摘要&#xff1a;前端自動化部署是通過工具和流程自動化實現前端代碼從開發完成到線上發布的全流程&#xff0c;減少人工操作、提高效率并降低出錯風險。核心目標減少重復操作&#xff1a;自動化構建、測試、部署等步驟&#xff0c;替代手動上傳服務器等低效方式。提升發布效率…

peewee中db.create_tables(tables, safe=True),safe=True作用

db.create_tables(tables, safeTrue) 中的 safeTrue 參數的作用是 防止在表已經存在的情況下引發錯誤。 具體來說&#xff1a; 當 safeTrue 時&#xff1a;Peewee 會在生成的 SQL 語句中加入 IF NOT EXISTS 子句&#xff08;例如&#xff1a;CREATE TABLE IF NOT EXISTS my_tab…