Java—认识异常 ( ̄▽ ̄)~*

news2024/11/28 14:51:06

目录:

一、异常的概念和体系结构:

1、异常的概念:

 2、异常的体系:

3、异常的分类: 

二、异常的处理:

1、防御式编程:

  1)、 事前防御型(LBYL) :

 2)、事后认错型(EAFP):

2、异常的抛出:

3、异常的捕获:

1)、声明异常throws:

※ 2)、try-catch捕获并处理异常:

 3)、fianlly

4、异常的处理流程:

三、自定义异常:

总结:


一、异常的概念和体系结构:

1、异常的概念:

     我相信,在我们在运行代码的时候,总会出现一些问题。所出现的这些问题,我们在Java中,我们将程序在执行中,出现的不正常的行为,称之为异常。

     那么有几种异常在我们写代码的时候经常遇到,比如:

1、算数异常:

我们来看看,什么叫做算数异常呢,直接看代码:


2、数组越界异常: 

       我们在使用到数组的时候呢,是不是经常的遇到或听到数组越界这个词,那么它的异常是什么样的呢? 我们来看看啊,直接看代码:

   当然在这个异常之后,再执行代码就不会再执行了。 


3、空指针异常: 

    对于空指针还是很好理解的,我们看看代码,就可以看懂了:     对于这个之后要是有代码,也是不会执行的,所以在这里呢,我呢就不在进行举例了,和上面是一样的。 

   所以从这几个例子就可以看出,对于异常来说呢,对于不同的异常,就会出现不同的结果。

   在Java中不同的异常,都有其对应的类来进行描述。 


 2、异常的体系:

   对于异常来说,它有很多的种类,所以在Java中维护了一个异常的体系结构。我们看图片来看看是什么样的


么这些都是什么意思呢,我知道你很急,但你先别急,现在我们来一一介绍:

Throwable:是异常类型的最顶层,它呢会派生出两个子类,这两个子类都是非常的重要的。

Error:这个就是Java虚拟机无法解决的问题,比如呢:内存的资源耗尽,JVM的内部错误,这些呢都是Error,最典型的,也是经常发生的就是:陷入死循环,使资源耗尽而出现的异常。

Exception:这个就是当程序产生异常后,程序员可以根据代码进行解决的异常,就是这个。 

我们接下来看看。Exception这个异常的分支,都派生出的那两个子类都是什么意思。


3、异常的分类: 

1、运行时异常/非受查异常:

     这个异常呢,就是我们上面的那些算数异常、数组越界异常、空指针异常等。就是运行时异常,在不运行时不会报错,只有运行时才会报错。

2、编译时异常/受查异常:

        这个呢,就是在我们讲抽象类和接口的时候呢,讲的深度拷贝就是一个例子,我们来重新看一下:

   

   当然这种的就不是异常了,这个只是代码写的问题,不是异常。 

   那么我们在认识异常之后呢,我们就要想一想我们要是出现了Exception这种的异常的时候,我们要如何处理异常呢?接下来我们来看看:


二、异常的处理:

1、防御式编程:

      错误的代码是客观的,我们要在出错前提示程序员,让其知道是哪里出现了问题,对于实现这种方法的方式主要有:

  1)、 事前防御型(LBYL)

  这种的呢就是事前防御型的,处理异常的方法。

  这个方式是有缺陷的:正常的代码流程和处理错误的流程混在一起,使代码过于混乱了。

  我们接下来讲的就是我们Java中常用的方式。 

 2)、事后认错型(EAFP)

   我们在事情发生后认错,比事前确认可不可以做,更容易获取原谅,也就是先斩后奏。 

   在这种方法中呢,我们就要了解并且熟悉Java中的一些处理异常的关键词:try、throw、catch、finally、throws 这5个关键字。我们来看看如何使用的:

 还是同样对于微信的登陆:

        这里我们看到了5个关键词的其中其中两个,那么这两个是什么意思,并且对于那3个又是什么意思呢? 

        在了解这个之前我们先来了解 事后认错型的优点什么,为什么我们在Java中要使用这个来处理程序的异常。

      优点:正常的代码流程和处理错误的流程是分开的,这样呢会使程序员更加的关注正确的流程                   代码,使得代码更加的清晰,可以更好的理解代码的流程和步骤。

      接下来我们来看看它们5个的作用是什么,又是如何实现的。 


2、异常的抛出:

    在我们的程序出现错误的时候,这个时候呢,就需要把错误信息告诉程序员,出现了什么错误。

    在Java中呢,我们可以使用throw关键字,来抛出一个指定的异常对象,将其信息告诉我们程序员。我们来看看如何使用这个throw这个关键字: 

    那我们看到这时,就会有人有疑问了,我们抛出的异常和编译器给我们的异常爆出的不是一样的吗?我们又为什么要这么写?当然不一样了,我们看看,我们这个代码可以如何更改:    由此我们就可以知道,我们抛异常的代码要如何写了吧~我们来看公式:

      throw new XXXException("产生异常的原因");

   当然对于我们使用throw抛出异常的时候我们呢,有一些注意事项要进行注意一下:

• throw要写在方法体的内部。

• throw抛出的对象必须是Exception本身又或者是Exception的子类对象,但是我们在抛异常的      时候要特殊注意一下如果抛出的是RunTimeException本身又或者是RunTimeException子类        的时候,可以不做任何的处理,可以交给JVM来进行处理。

• 如果我们抛出的是编译时异常,那么我们必须要进行处理,要不然代码无法编译。

• 当我们throw异常后,其后代码不会再执行。我们来看看:

    现在呢,我们知道了对于异常的抛出,那么当我们抛出异常之后呢,我们是不是要捕获并且解决这个异常呢?那么我们接着往下看: 


3、异常的捕获:

  在我们Java中呢,我们有两捕获异常的方法:声明异常throws 和 try-catch捕获处理异常 

我们分别来一一了解一下:

1)、声明异常throws:

       这个方法是处在方法列表的后面,这个实在当用户不想解决这个代码的时候,我们可以使用这个方法,来把异常抛给方法的调用者来处理这个方法。就是当我们方法不想处理这个异常的时候,我们抛给方法的调用者来处理。

       这个方法我们之前见过,在我们介绍编译时异常的时候就使用过。我们还是看这个例子:

   那么假如我们也不想在调用者中进行处理呢?我们又要如何做到呢?我们可以继续声明异常:

   但还我们需要注意的是当我们交给JVM来处理的时候呢,就会终止程序了。 

当我们使用这个声明异常的时候呢,我们可以声明多个异常,比如:

     我们需要叫逗号来进行分割,但是呢我们需要注意的是,当我们声明多个异常的时候呢,如果出现父子关系呢,我们可以直接声明父类就可以了。我们来举个例子:

 

   继承IOEcepection这个异常类

   这里我们就可以非常容易理解这个父子类关系了 。

由此上面的这些实例我们就可以知道我们throws声明异常的语法了:

修饰词  返回值类型  方法名(参数列表) throws 异常类型1, 异常类型2, 异常类型3..... {

}

在我们使用throws声明异常的时候要注意的是:

     • throws必须使用在参数列表的后面。

     • throws声明的异常必须是Exception本身或者是Exception的子类。

我们接下来要介绍的try-catch方法是非常重要的,它使我们对于异常的捕获并且处理的方法。


※ 2)、try-catch捕获并处理异常:

      我们虽然在异常捕获的时候就说过,关于捕获异常有两种方法,但是到是当我们在了解throws方法之后呢,就知道了其并没有真正的处理异常,只是将异常声明,并且要抛给调用者来处理异常。所以当我们真正捕获异常的时候其实只有一个:try-catch方法。

try-catch方法:

try {

//可能发生异常的代码

}catch (异常类型 e) {

//对捕获的代码进行处理

}catch (异常类型 e) {

//对捕获的代码进行处理

}.......

我们先来看看这个是怎么使用的:

   执行代码的结果:

我们对于代码进行更改再看看结果如何: 

异常的处理方式: 

      在Java中我们有很多种的异常,不可能是每种异常都需要使用try-catch方法进行处理异常。我们呢要根据实际情况来决定。比如呢:

     • 对于比较严重的异常(比如 和内存相关的),我们应该直接让程序崩溃,防止产生更严重的后果。

     • 对于不是太严重的问题,我们可以捕获异常并通知程序员解决异常。

     • 对于有些可能会恢复的异常呢,我们可以尝试进行重试代码。

注意: 

     • try内当抛出异常之后,在异常后面的代码就不会执行。

     • 

     那么我们要怎样才能打印哪里出现的异常呢?很简单,我们直接在catch中实现: 

   这样做我们就可以得到错误的信息了。 

    • 在try当中我们可能会捕获很多的异常,那么我们必须要用catch多次接收,多次捕获

   这样我们就可以在捕获 数组越界异常 还可以 捕获空指针异常 了。 

    那么看到这里可能呢就会有一些疑问了,我们可以接收多个异常的话,那我们可不可以一次性捕获多个异常呢?比如这样:

我们来看看输出的结果:    所以我们不会捕获多个异常的,这个是需要注意的。

对于这个代码我们是可以进行简化的,当然简化的不是最好的,为什么呢?简化之后我们代码不应该更简洁了吗?为什么不是最好的?我们来看看:

     那为什么是不好的呢?这是因为,当我们打印处理.....异常的时候,那么我们是处理了 数组越界异常呢 还是 空指针异常呢 ?这就是个问题了。所以不是很建议这样去处理异常。但是也是可以写滴。

   对于这个简写,有的人是不是会这样写:

       如果是这样写的话,就更有问题了,对于Exception来说有很多的子类异常,我们使用这个的时候,就不知道到底是什么异常导致的了。我们再来看段代码:

     Exception是NullPointerException的父类,当我们捕获到Exception这个异常了,它的子类就捕获不到了,所以相当于后面的catch就是多余的了。不能所有的异常都用Exception来接收。

     但是呢,我们的代码可以这样写:

  这样就是先进行接收空指针异常,在之后再进行接收Exception的这个父类异常进行兜底。

 所以我们在catch是要先写子类再写父类,在有父子类关系的时候。 


 3)、fianlly

     我们把其余的四个关键词都进行了了解,现在我们只剩下finally了,那么接下来我们来看看对于finally是怎样进行使用的,又有什么作用。

    在了解之前,我们先来了解一下别的东西,在我们写程序的时候呢,我们肯定有一些特殊的代码,不论我们的程序能否正常执行,我们都需要执行这些代码,比如呢在程序中打开的资源:数据库,网络连接,在程序中不论是否正常,必须要对资源进行回收。在我们出现异常的时候就会退出try-catch方法,有些代码就不会执行,这时候就需要使用finally来解决之个问题。

 我们来看看代码:

    那么这个时候呢,就会有人问了我们的finally和在try-catch方法外面写的代码也可以执行,那么我为啥还要用finally呢?

    那么我们在来看这个例子就知道了,我们为什么使用finally代码。 我们来看:

      OK,我们可以看到这里的在try-catch之后的代码,没有被执行,内存流没有被释放,导致资源泄露。 但是fianlly里的代码还是被执行了。所以我们一般把对于资源的释放代码放在fianlly里,进行扫尾工作。我们来更改一下代码看看:

    我们还可以对于这个代码进行一定的优化: 

在这里我们有一个非常特殊的一个问题,我们来看:     fianlly呢是做的一个是善后工作,可以理解为,把10给覆盖了,但是我们不要这么写代码,这是不好的。


4、异常的处理流程:

   如果方法本身没有处理异常就会,向上传递,最后就会交给JVM,导致程序终止。

我们来看事例:

    先是程序本身有没有处理异常,如果没有,就交给调用者,再看有没有处理异常,再到main函数中看看有没有处理异常,如果还是没有处理异常,就交给JVM来处理,但是在这会终止程序 

所以我们总结可知:

     • 程序先执行try中的代码

     • 如果try中的代码执行出现异常,就会到catch中寻找和其出现异常匹配的异常

     • 如果找到了,就会执行catch里面的方法,如果没有找到的话,就会向上传递到调用者

     • 无论是否找到匹配的,finally的里的代码都会执行

     • 如果上层调用者也没有处理异常,就继续往上层调用,一直到main中,如果还是没有处理异常的话,就会让JVM来处理,这是会使程序终止。

三、自定义异常:

    在Java中呢,我们有很多的异常的类,但是呢,还是不能表示所有遇到的异常,所以这时候我们就要自己维护这些异常。

   比如我们现在有很多的软件是不是都有登录这个操作啊。但是呢,在Java中没有系统自带的登录异常,所以这时候呢,我们就要自己维护一个登录异常的操作。

   下面我们来看看,我们怎样来自定义登录异常的:

    我们可以看到,我们代码出现了错误,这是为什么呢?这是因为我们继承的是Exception,使其自定义的异常称为编译时异常/受查异常,这时候呢因为我们没有声明异常,我们不知道是哪种异常,所以我们要在抛异常的方法后面声明可能会出现的异常,才可以。我们来看: 在我们自定义异常的时候呢,我们有一些注意事项:

    • 在我们自定义异常的时候通常继承Exceprion或者是RuntimeException

    •  在我们继承Exception时候呢,我们自定义的异常称为 编译时异常/受查异常。

    •  在我们继承RuntimeException时候呢,我们自定义的异常称为 运行时异常/非受查异常。

    在我们集成RuntimeException的时候呢,如果我们在抛异常的方法后面没有声明异常,也是不会出错的。 但是呢,一般我们还是声明一下异常比较好。 


总结:

     OK,这次的分享就到这里就结束了,在这个之后呢,对与我们Java的基础就告一段落了,接下来我们就要进入数据结构的章节了,让我们敬请期待吧。拜拜~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2060267.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言典型例题47

《C程序设计教程(第四版)——谭浩强》 习题3.7 输入4个整数,要求按照从小到大的顺序输出 4个数之间进行比较,冒泡排序最最最详细过程,如果想更改为任意数之间相互比较,只需要修改两个地方(数组大…

cocoscreator怪物实时寻路AI

这章主要介绍怪物AI 1:环境 cococreator2.4.* 2:规则 当前规则很简单,就是跳上,跳下 一个土块 3:上代码 // Learn cc.Class: // - https://docs.cocos.com/creator/manual/en/scripting/class.html // Learn Attri…

C++智能指针配合STL模板类

代码 #include <unordered_map> #include <set> #include <memory> class ResID { public:using SP std::shared_ptr<ResID>;ResID() default;ResID(const std::string& id, const std::string& type): m_id(id), m_type(type){}public:~Re…

SAM 2——视频和图像实时实例分割的全新开源模型

引言 源码地址&#xff1a;https://github.com/facebookresearch/segment-anything-2 过去几年&#xff0c;人工智能领域在文本处理的基础人工智能方面取得了显著进步&#xff0c;这些进步改变了从客户服务到法律分析等各个行业。然而&#xff0c;在图像处理方面&#xff0c;我…

Python高手如何做到一键更新代码?

声明&#xff1a;此篇为 ai123.cn 原创文章&#xff0c;转载请标明出处链接&#xff1a;https://ai123.cn/2186.html ​Hey&#xff0c;Python搞手们&#xff0c;&#x1f44b;&#xff0c;你们是否也头疼代码维护的重重难关&#xff1f;别担心&#xff0c;今天就给你们带来一手…

【功能】Lua层的全局事件管理系统

1.EventManager 全局的管理类 2.EventType 事件类型 3..Lua层Common工具目录去require对应文件目录的脚本文件 --事件类型 local EventType {TestMsg 1&#xff0c; }return EventType local EventManager class(); EventManager.msgMap {}local function HaveSameFunc(…

Linux 搜索历史命令Ctrl+R

最近使用CtrlR来搜索历史命令&#xff0c;对比速度比history 快一下&#xff0c;且看起来高级。记录如下&#xff1a;命令1&#xff1a;history 功能&#xff1a;显示当前Linux终端输入过的历史命令。案例&#xff1a;使用history 出来的结果很多&#xff0c;通常和grep 过滤&a…

抗菌肽LL-37;LLGDFFRKSKEKIGKEFKRIVQRIKDFLRNLVPRTES;CAS:154947-66-7

【抗菌肽LL-37 简介】 LL-37是一种由37个氨基酸残基组成的抗菌肽&#xff0c;它是人类cathelicidin家族中的唯一成员。LL-37具有广泛的抗菌活性&#xff0c;能够对抗革兰氏阳性菌和革兰氏阴性菌&#xff0c;以及真菌和病毒。除了直接的抗菌作用&#xff0c;LL-37还具有免疫调节…

你是如何克服编程学习中的挫折感的?(-@-^-0-)

在编程学习中遇到挫折感是极为常见且正常的现象&#xff0c;因为编程往往涉及解决复杂问题、理解抽象概念以及不断试错的过程。 以下是一些建议&#xff0c;帮助你在面对挫折时调整心态&#xff0c;继续前行&#xff1a; 接受失败是成长的一部分&#xff1a;首先要认识到&#…

linux之网络子系统-tcpdump 原理

一、tcpdump 的用途 tcpdump是Linux系统抓包工具&#xff0c;tcpdump基于libpcap库&#xff0c;根据使用者的定义对网络上的数据包进行截获&#xff0c;tcpdump可以将网络中传送的数据包中的"头"完全截获下来提供分析&#xff0c;支持针对网络层、协议、主机、网络或…

刷题篇 - 03

题目一&#xff1a; 203. 移除链表元素 - 力扣&#xff08;LeetCode&#xff09; public ListNode removeElements(ListNode head, int val) {//1. 如果链表为null&#xff0c;直接返回headif (head null) {return head;}//2. 定义快慢指针ListNode pre head;ListNode del …

工业数据采集网关简介-天拓四方

随着工业4.0和物联网&#xff08;IoT&#xff09;技术的深入发展&#xff0c;工业数据采集网关作为连接现场设备与上层管理系统的关键节点&#xff0c;其在智能工厂中的作用愈发凸显。本文将深入探讨工业数据采集网关的功能、特点、应用场景及其实操性&#xff0c;以期为读者提…

【JPCS出版】第三届机械、航天技术与材料应用国际学术会议 (MATMA 2024)

第三届机械、航天技术与材料应用国际学术会议(MATMA 2024)定于2024年08月30-9月1日在中国呼和浩特隆重举行。 本会议由内蒙古工业大学主办&#xff0c;主要围绕“机械工程”、“航天技术”与“材料应用”等最新研究领域展开研讨&#xff0c;为来自国内外高等院校、科学研究所、…

【SpringCloud】(一文通)SpringCloud 环境和工程搭建

目 录 一. 开发环境安装二. 案例介绍2.1 需求2.2 服务拆分 三. 数据准备四. 工程搭建4.1 构建父子工程4.1.1 创建父工程4.1.2 创建子项目-订单服务4.1.3 创建子项目-商品服务 4.2 完善订单服务4.2.1 完善启动类, 配置文件4.2.2 业务代码4.2.3 测试 4.3 完善商品服务4.3.1 完善启…

Cesium实现单个无人机飞行

通过一组坐标&#xff0c;实现平滑的无人机飞行效果 测试步骤&#xff1a; 1、手动填写坐标并记录坐标(可通过点击球面查看坐标信息) 2、点击初始化&#xff0c;载入相应的坐标信息 3、点击漫游&#xff0c;镜头会平滑演进 低配置云服务器&#xff0c;首次加载速度较慢&…

设备状态图表-甘特图

1.背景&#xff1a;设备状态监控图表&#xff0c;监控不同状态的时间段&#xff0c;可以使用甘特图来展示效果 鼠标经过时的数据提示框 2、代码实现 <template><divref"ganttChartRefs":style"{ height: 6.2rem, width: 100% }"class"bg…

利用ai写作软件,一键智能改写文案很简单

在当今快节奏的时代&#xff0c;科技的发展日新月异&#xff0c;人工智能&#xff08;AI&#xff09;已经逐渐融入到我们生活的各个方面。其中&#xff0c;AI写作工具的出现为文案创作带来了极大的便利&#xff0c;让一键智能改写文案变得简单而高效。 AI写作工具利用先进的算法…

项目技巧1

目录 创建项目工程的技巧 示例&#xff1a;创建父工程 第一步&#xff1a;初始化maven项目 第二步&#xff1a;使用标签 抽取依赖的资源版本号&#xff0c;方便后续调整 第三步&#xff1a;配置父工程锁定的版本&#xff0c;使用 该标签的作用&#xff1a;锁定资源的版本号&…

初探Raft算法

在分布式系统有一个经典的CAP理论&#xff0c;C&#xff1a;一致性&#xff0c;即集群中所有节点都应该是一致的。A&#xff1a;可用性&#xff0c;集群一直处于可用状态。P&#xff1a;分区容错性&#xff1a;即复制所有数据到集群的所有节点&#xff0c;保证即使出现网络分区…

TQRFSOC开发板47DR,LMK04832更新配置

在利用RFSOC开发板进行项目开发时&#xff0c;面对多样化的时钟需求&#xff0c;巧妙地配置LMK04832时钟管理芯片以输出精确的时钟信号显得尤为重要。本期内容将讲解如何通过ZYNQ更新LMK04832的配置&#xff0c;以满足您的特定时钟需求。 每次配置成功后&#xff0c;配置文件都…