详解Java中的异常体系机构(throw,throws,try catch,finally)
目录
一.异常的概念
二.异常的体系结构
三.异常的处理
异常处理思路
LBYL:Look Before You Leap
EAFP: It's Easier to Ask Forgiveness than Permission
异常抛出throw
异常的捕获
提醒声明throws
try-catch捕获处理
finally的作用
四.自定义异常类
一.异常的概念
有一句话说的很好 ”程序员不是在写BUG就是在改BUG” ,在日常开发中,程序员绞尽脑汁的去写出完美的代码,但是在程序运行过程中难免回遇见一些奇奇怪怪的问题。而这些问题与BUG总是很难去控制,用人类的思维去看明明是很完美的一个逻辑处理,但是交给编译器就产生的结果总会与我们的预期大相径庭,在Java中,我们将程序执行过程中发生的不正常的行为称为异常,比如什么算数异常啊,数组越界异常啊,空指针异常啊这都属于异常的范围,我们统称为异常
System.out.println(10 / 0);// 执行结果Exception in thread "main" java.lang.ArithmeticExceptionint[] arr1 = {1, 2, 3};System.out.println(arr1[100]);// 执行结果Exception in thread "main" java.lang.ArrayIndexOutOfBoundsExceptionint[] arr2 = null;System.out.println(arr2.length);// 执行结果Exception in thread "main" java.lang.NullPointerException
并且我们可以看见在Java中对于不同的异常,都有对应的类来描述
二.异常的体系结构
实际上异常的种类是很多的,为了应对不同的异常或者错误,Java提供了一个非常庞大的异常体系机构供程序员来更好的维护代码的安全性,如下图所示
异常可能发生在编译阶段,可能发生在运行阶段,因此我们可以按照异常发生的时间段将其进行分类:
- 编译时异常,也叫做受查异常
- 运行时异常,也叫做非受查异常
但是诸如将单词拼写错误导致的问题我们程序出现问题的情况不属于异常
三.异常的处理
代码中存在异常并不是什么奇怪的事情,但是在出现异常后,我们需要及时通知程序员去修改,对于异常的处理,我们分为俩种思路
异常处理思路
LBYL:Look Before You Leap
也就是说我们在操作之前就对异常做出充分的检查,也就是事先防御型,比如我们在设计一款游戏的时候,我们就需要对其中可能发生的每一个错误做出处理机制和避免机制
boolean ret = false;ret = loginGame();if (!ret) {//处理登陆游戏错误;return;}ret = startMatch();if (!ret) {//处理匹配错误;return;}ret = conGame();if (!ret) {//处理游戏确认错误;return;}ret = choiceChar();if (!ret) {//处理选择英雄错误;return;}ret = loading();if (!ret) {//处理载入游戏错误;return;}
但这样的处理会有一个缺陷:正常流程和错误处理流程代码混在一起, 代码整体显的比较混乱
EAFP: It's Easier to Ask Forgiveness than Permission
这样的思想主要解决的问题不是如何提前避免异常,而是在异常出现以后如何进行合理的应对
try {loginGame();startMatch();conGame();choiceChar();loading();} catch (loginGame异常) {//处理登陆游戏错误;} catch (startMatch异常) {//处理匹配错误;} catch (conGame异常) {//处理游戏确认错误;} catch (choiceChar异常) {//处理选择英雄错误;} catch (loading异常) {//处理载入游戏错误;}
在Java中对于异常处理的核心机制就是EAFP,Java中常用的有5个异常处理的关键字:
- throw
- try
- catch
- final
- throws
异常抛出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);}
注意:
- throw必须写在方法体内部
- 抛出的对象必须是Exception 或者 Exception 的子类对象
- 如果抛出的是 RunTimeException 或者 RunTimeException的子类,则可以不用处理,直接交给JVM来处理
- 如果抛出的是编译时异常,用户必须处理,否则无法通过编译
- 异常一旦抛出,其后的代码就不会执行
异常的捕获
异常的捕获就是指我们对异常的处理,通常我们有俩种方式去处理:
- 异常声明throws
- try-catch捕获处理
提醒声明throws
处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛给方法的调用者来处理。也就是说当前方法不处理异常,提醒方法的调用者处理异常。
语法格式:
修饰符 返回值类型 方法名 (参数列表) throws 异常类型1,异常类型2...{
}
public class Config {File file;/*FileNotFoundException : 编译时异常,表明文件不存在此处不处理,也没有能力处理,应该将错误信息报告给调用者,让调用者检查文件名字是否给错误了*/public void OpenConfig(String filename) throws FileNotFoundException {if (filename.equals("config.ini")) {throw new FileNotFoundException("配置文件名字不对");}// 打开文件}
}
注意事项:
- throws必须跟在方法参数列表之后
- 抛出的问题必须是Exception 或者 Exception的子类对象
- 方法内部如果抛出了多个异常,throws之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型具有父子关系,直接声明父类即可
- 调用声明抛出的异常方法时,调用者必须对异常做出处理,或者继续使用throws抛出
示例:
class Config {File file;// FileNotFoundException 继承自 IOExceptionpublic void OpenConfig(String filename) throws IOException {if(filename.endsWith(".ini")){throw new IOException("文件不是.ini文件");}if(filename.equals("config.ini")){throw new FileNotFoundException("配置文件名字不对");}// 打开文件}public void readConfig(){}public void openConfig(String s) {}public static void main(String[] args) throws IOException {Config config = new Config();config.openConfig("config.ini");}
}
try-catch捕获处理
刚才我们提到的throws并没有对异常做出处理,他只是将异常报给调用者,让调用者去处理,而如果要对异常真正的处理就需要使用try-catch。
try-catch的一般使用语法如下,其中catch:可以有一个也可以有多个,根据具体需求分配,finally可以有也可以没有,但是如果有的话finally中的代码就一定会执行,并且try中的代码也可以不出现异常:
try{// 将可能出现异常的代码放在这里}catch(要捕获的异常类型 e){// 如果try中的代码抛出异常了,此处catch捕获时异常类型与try中抛出的异常类型一致时//或者是try中抛出异常的基类时,就会被捕获到//对异常就可以正常处理,处理完成后,跳出try-catch结构,继续执行后序代码}catch(异常类型 e){// 对异常进行处理}finally{// 此处代码一定会被执行到}
}
示例:
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("异常如果被处理了,这里的代码也可以执行");}
}
注意:
- try块内抛出异常位置之后的代码将不会被执行
- 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到JVM收到后中断程序----异常是按照类型来捕获的
- try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获----即多种异常,多次捕获
- 如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错误
finally的作用
在写程序时,有些特定的代码,不论程序是否发生异常,都需要执行,比如程序中打开的资源:网络连接、数据库连接、IO流等,在程序正常或者异常退出时,必须要对资源进进行回收。另外,因为异常会引发程序的跳转,可能导致有些语句执行不到,finally就是用来解决这个问题的。
关于异常的处理方式,异常的种类有很多,我们要根据不同的业务场景来决定
- 对于比较严重的问题(例如和算钱相关的场景), 应该让程序直接崩溃, 防止造成更严重的后果
- 对于不太严重的问题(大多数场景), 可以记录错误日志, 并通过监控报警程序及时通知程序猿
- 对于可能会恢复的问题(和网络相关的场景), 可以尝试进行重试
- 在我们当前的代码中采取的是经过简化的第二种方式. 我们记录的错误日志是出现异常的方法调用信息, 能很快速的让我们找到出现异常的位置. 以后在实际工作中我们会采取更完备的方式来记录异常信息
四.自定义异常类
Java中虽然已经内置了丰富的异常类, 但是并不能完全表示实际开发中所遇到的一些异常,此时就需要维护符合我们实际情况的异常结构,自定义异常通常会继承自 Exception或RunTimeException
- 继承自 Exception 的异常默认是受查异常
- 继承自 RunTimeException 的异常默认是非受查异常
具体方式:
- 自定义异常类,然后继承自Exception 或者 RunTimeException
- 实现一个带有String类型参数的构造方法,参数含义:出现异常的原因
例如我们实现一个用户登陆功能:
class UserNameException extends Exception {public UserNameException(String message) {super(message);}
}
class PasswordException extends Exception {public PasswordException(String message) {super(message);}
}
class LogIn {private String userName = "admin";private String password = "123456";public static void loginInfo(String userName, String password)throws UserNameException,PasswordException{if (!userName.equals(userName)) {throw new UserNameException("用户名错误!");}if (!password.equals(password)) {throw new PasswordException("用户名错误!");}System.out.println("登陆成功");}public static void main(String[] args) {try {loginInfo("admin", "123456");} catch (UserNameException e) {e.printStackTrace();} catch (PasswordException e) {e.printStackTrace();}}
}
本次的分享就到此为止了,希望我的分享能给您带来帮助,也欢迎大家三连支持,你们的点赞就是博主更新最大的动力!
如有不同意见,欢迎评论区积极讨论交流,让我们一起学习进步!
有相关问题也可以私信博主,评论区和私信都会认真查看的,我们下次再见
相关文章:

详解Java中的异常体系机构(throw,throws,try catch,finally)
目录 一.异常的概念 二.异常的体系结构 三.异常的处理 异常处理思路 LBYL:Look Before You Leap EAFP: Its Easier to Ask Forgiveness than Permission 异常抛出throw 异常的捕获 提醒声明throws try-catch捕获处理 finally的作用 四.自定义异常类 一.异…...

【jvm】虚拟机之堆
目录 一、堆的核心概述二、堆的内存细分(按分代收集理论设计)2.1 java7及以前2.2 java8及以后 三、堆内存大小3.1 说明3.2 参数设置3.3 默认大小3.4 手动设置3.5 jps3.6 jstat3.7 OutOfMemory举例 四、年轻代与老年代4.1 说明 五、对象分配过程5.1 说明5…...

二百零五、Flume——数据流监控工具Ganglia单机版安装以及使用Ganglia监控Flume任务的数据流(附流程截图)
一、目的 Flume采集Kafka的数据流需要实时监控,这时就需要用到监控工具Ganglia 二、Ganglia简介 Ganglia 由 gmond、gmetad 和 gweb 三部分组成。 (一)第一部分:gmond gmond(Ganglia Monitoring Daemon)…...

解决Resolving Android Dependencies问题
无论是谷歌的Admob,还是Unity的Level play, 在windows(win10, win11)下,都出现了resolving android dependencies 报错并且卡住的问题,如图: 主要错误,是找不到这个gradlew.bat文件。 在指定位置…...

深度学习技术前沿:探索与挑战
深度学习技术前沿:探索与挑战 一、引言 近年来,深度学习作为人工智能领域的重要分支,取得了令人瞩目的成就。它凭借强大的学习能力和出色的性能,在图像识别、语音识别、自然语言处理等众多任务中展现出巨大潜力。本文将深入探讨深…...

2023-11-24--oracle--实验--[Merge 语句]
oracle--实验---Merge语句 1.认知Merge 语句 • merge 语句是 sql 语句的一种。在 SQL server 、 Oracle 数据库中可用, MySQL 中不可用。 • merge 用来合并 update 和 insert 语句。目的:通过 merge 语句,根据一张表( 原数据表…...

2023亚太杯C题30页高质量word成品论文+五小问py代码+数据集+运行结果图
迈向绿色未来:中国新能源电动汽车综合分析 摘要 (完整版获取在文末!!!) 这项深入研究探讨了中国新能源电动汽车 (NEEV) 的新兴领域,涵盖从市场动态到生 态影响等广泛方面。问题一深入探讨新能…...
【docker】安装redis和mysql生产实战
docker安装诸如redis,mysql等程序非常方便,但是如果不是为了学习,生产环境的部署还是要注意很多问题的 mysql docker pull mysql:5.7mkdir -p /usr/docker/mysql/{conf,logs,data}docker run -d -p 3306:3306 --privilege...
【nlp】3.1 Transformer背景介绍及架构
Transformer背景介绍 1 Transformer的诞生2 Transformer的优势3 Transformer的市场4 Transformer架构4.1 Transformer模型的作用4.2 Transformer总体架构图4.2.1 输入部分4.2.2 输出部分包含4.2.3 编码器部分4.2.4 解码器部分1 Transformer的诞生 2018年10月,Google发出一篇论…...

喜报!美格智能连续五年荣获物联网100强企业
近日,由中国科学院主管、科学出版社主办的《互联网周刊》联合eNet研究院发布了“2023物联网企业100强”榜单,美格智能凭借在技术创新、市场表现、综合实力等多方面的健稳表现连续五年入选榜单。 《互联网周刊》创办于1998年,是最为权威的商业…...

『Confetti 喜庆散花插件の使用』
以下用 VUE3 语法 举例使用: npm install js-confetti<script setup lang"ts"> import JSConfetti from js-confetticonst confetti new JSConfetti()function showConfetti() {confetti.addConfetti() } </script><template><h1 …...

Axios 通过a标签下载文件 跨域下载
<!-- a标签占位 --><a ref"down" ></a>getTest() {this.$axios.request({url: https://cnv13.55.la/download?file_key3695fa9461a0ae59cf3148581e4fe339&handle_typeexcel2pdf,method: get,responseType: blob, // 切记类型 blob}).then(re…...

VR全景展示,“超前点播”打开娱乐行业线上营销门户
如今,人们的生活水平正在逐步提高,这种提高不仅仅是体现在衣食住行上,更多方面是体现在大众的娱乐活动上。我们可以看到,相比于过去娱乐种类的匮乏,现如今,各种娱乐活动可谓是百家争鸣,例如温泉…...

Mac安装配置typescript及在VSCode上运行ts
一、Mac上安装typescript sudo npm install -g typescript 测试一下:出现Version则证明安装成功 tsc -v 二、在VSCode上运行 新建一个xxx.ts文件,测试能否运行 console.log("helloworld") 运行报错:ts-node: command not…...

举个栗子!Tableau 技巧(260):文本表中省市县数据的灵活逐级下钻「方法二」
之前,我们分享过 🌰:实现地图中的省市县逐级下钻。有数据粉提出问题:如果不是地图,而是文本表,有什么办法可以像这样,实现地理位置逐级下钻呢? 文本表也是可以的。但是,…...

软著项目推荐 深度学习 opencv python 实现中国交通标志识别
文章目录 0 前言1 yolov5实现中国交通标志检测2.算法原理2.1 算法简介2.2网络架构2.3 关键代码 3 数据集处理3.1 VOC格式介绍3.2 将中国交通标志检测数据集CCTSDB数据转换成VOC数据格式3.3 手动标注数据集 4 模型训练5 实现效果5.1 视频效果 6 最后 0 前言 🔥 优质…...

【Java基础】Java导Excel攻略
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

maven打包可执行jar含依赖lib
修改pom.xml <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><!-- jdk8可用,其他jdk版本可能需改插件版本 --><version>2.3.7.RE…...

虾皮知虾数据分析软件:优化您的电商经营
在当今竞争激烈的电商市场,了解市场动态、分析竞争对手和产品趋势是成功经营的关键。虾皮知虾数据分析软件是一款强大的工具,为电商卖家提供了全面的数据采集和分析功能。本文将介绍虾皮知虾数据分析软件的特点和功能,以及如何利用它来优化您…...
uniapp开发小程序-如何判断小程序是在手机端还是pc端打开
官方说明 https://developers.weixin.qq.com/miniprogram/dev/devtools/pc-dev.html 小程序如何判断是 PC 平台? 通过 getSystemInfo 官方接口(platform 是 windows) 通过 UA(PC UA 包含 MiniProgramEnv/Windows) …...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...