认识Java中的异常

认识Java中的异常

1. 异常的概念与体系结构

异常不同于编译错误,语法错误

算数异常:

数组下标越界异常:

空指针异常:

异常其实就是一个一个的类,所有异常都继承了Throwable类,其派生出两个重要的子类, Error 和 Exception

其中Exception又分为两大类,一类是运行时异常/非受查异常,另一类为编译时异常/受查异常。

(1)运行时异常就是代码还没运行就报错了

对于这种异常有一个很明显的特点就是要处理掉异常才能继续运行

(2)编译时异常指的是Java虚拟机无法解决的严重问题

这种情况需要程序员手动去处理错误

总结:

1. Throwable:是异常体系的顶层类,其派生出两个重要的子类, Error 和 Exception

 2. Error:指的是Java虚拟机无法解决的严重问题,比如:JVM的内部错误、资源耗尽等,典型代表: StackOverflowError和OutOfMemoryError,一旦发生回力乏术。

3. Exception:异常产生后程序员可以通过代码进行处理,使程序继续执行。比如:感冒、发烧。我们平时所说 的异常就是Exception。

2. 异常的处理

防御式编程

(1)LBYL: Look Before You Leap. 在操作之前就做充分的检查. 即:事前防御型

        缺陷:正常流程和错误处理流程代码混在一起, 代码整体显的比较混乱

(2)EAFP: It's Easier to Ask Forgiveness than Permission. "事后获取原谅比事前获取许可更容易". 也就是先操 作, 遇到问题再处理. 即:事后认错型

        优势:正常流程和错误流程是分离开的, 程序员更关注正常流程,代码更清晰,容易理解代码 异常处理的核心思想就是 EAFP。

在Java中,异常处理主要的5个关键字:throw、try、catch、final、throws。

异常的抛出

        在编写程序时,如果程序中出现错误,此时就需要将错误的信息告知给调用者,比如:参数检测。 在Java中,可以借助throw关键字,抛出一个指定的异常对象,将错误信息告知给调用者

        程序员可以通过throw来抛出异常,也可以在抛出的异常创建构造方法

      

异常的捕获

        异常的捕获,也就是异常的具体处理方式,主要有两种:异常声明throws 以及 try-catch捕获处理

        异常声明throws:处在方法声明时参数列表之后,当方法中抛出编译时异常,用户不想处理该异常,此时就可以借助throws将异常抛 给方法的调用者来处理。即当前方法不处理异常,提醒方法的调用者处理异常。

        以克隆为例:

        当加上throws CloneNotSupportedException后,声明当前方法可能会出现异常,但是这里的异常并没有被处理,只是交给了JVM处理,一旦交给JVM处理,程序就立即终止了。(即告诉JVM这里会出现异常)

【注意事项】

1. throws必须跟在方法的参数列表之后

2. 声明的异常必须是 Exception 或者 Exception 的子类

3. 方法内部如果抛出了多个异常,throws之后必须跟多个异常类型,之间用逗号隔开,如果抛出多个异常类型 具有父子关系,直接声明父类即可。

4. 调用声明抛出异常的方法时,调用者必须对该异常进行处理(需要用到try-catch),或者继续使用throws抛出。(此处以克隆为例,当方法抛出异常时,在main调用这个方法需要处理该异常,或者也抛出该异常)

try-catch捕获并处理

        throws对异常并没有真正处理,而是将异常报告给抛出异常方法的调用者,由调用者处理。如果真正要对异常进行 处理,就需要try-catch。

以克隆为例:当方法中存在异常会进入catch部分,执行catch中的语句,当不抛出异常时会继续执行,不会进入catch部分。

进一步理解

当处理完异常,想定位异常的准确位置可以通过printStackTrace()

当想处理两个不同类型的异常时,可以用多个catch()

也可以用分隔符|来进行类型的分割(但分隔符不好确定异常的种类,通常是使用多个catch())

但当有多个异常时,只会打印出一个异常。

不能任何异常都用Exception,Exception是所有异常的父类,此时从上到下过滤的

【注意事项】

1. try块内抛出异常位置之后的代码将不会被执行

2. 如果抛出异常类型与catch时异常类型不匹配,即异常不会被成功捕获,也就不会被处理,继续往外抛,直到 JVM收到后中断程序----异常是按照类型来捕获的

3. try中可能会抛出多个不同的异常对象,则必须用多个catch来捕获----即多种异常,多次捕获。如果异常之间具有父子关系,一定是子类异常在前catch,父类异常在后catch,否则语法错误:

4. 可以通过一个catch捕获所有的异常,即多个异常,一次捕获(不推荐)

由于 Exception 类是所有异常类的父类. 因此可以用这个类型表示捕捉所有异常.

finally

        finally用于资源的释放,是否出现异常finally都可以实现断后操作。close()可以写入finally当中(try后面也可以跟小括号,可实现输入)

注意:finally中的代码一定会执行的,一般在finally中进行一些资源清理的扫尾工作

关于finally的执行是最后,需要特殊记一下(理论上返回的值是10,但不是立刻返回的,底层将其修改为20)

一般我们不建议在 finally 中写 return (被编译器当做一个警告)

异常的处理流程

        处理异常的顺序:从方法本身来处理异常,到谁调用此方法谁处理异常,最后交给JVM来处理异常

如果向上一直传递都没有合适的方法处理异常, 最终就会交给 JVM 处理, 程序就会异常终止(和我们最开始未使用 try catch 时是一样的)

【异常处理流程总结】

程序先执行 try 中的代码

如果 try 中的代码出现异常, 就会结束 try 中的代码, 看和 catch 中的异常类型是否匹配.

如果找到匹配的异常类型, 就会执行 catch 中的代码

如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.

无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).

如果上层调用者也没有处理的了异常, 就继续向上传递.

一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止.

3.throw 和 throws 的区别

throw是扔出一个程序,而throws是在方法声明的地方声明一个异常

4. 自定义异常类

Java 中虽然已经内置了丰富的异常类, 但是并不能完全表示实际开发中所遇到的一些异常,此时就需要维护符合我 们实际情况的异常结构.

以用户登录为例

此时我们想自定义用户账户和密码异常,可以定义一个异常类继承​​​​​​​RuntimeException,并且重写

两个构造方法

继承RuntimeException和Exception的不同

继承RuntimeException,异常为编译时异常或者受查异常。

继承Exception,异常为运行时异常或者非受查异常。

解决方法如下

(1)自己用try和catch处理异常,同时注意不要再去main中去解决异常

(2)声明异常

注意事项

自定义异常通常会继承自 Exception 或者 RuntimeException

继承自 Exception 的异常默认是受查异常

继承自 RuntimeException 的异常默认是非受查异常

Read more

【C++深学日志】C++“类”的完全指南--从基础到实践(一)

【C++深学日志】C++“类”的完全指南--从基础到实践(一)

假想一下,你是一个顶级汽车设计师,你的任务不是亲自拧紧每一个螺丝,而是要设计出一幅“汽车蓝图”,你在图纸上设计了一辆汽车所需的一切:车轮、车灯、V8发动机、方向盘等,你手上这份设计好的蓝图就相当于我们今天要讲的C++中的“类”,它规定了汽车的属性(例如:离合器)和方法(功能:换挡),它本身并不是一辆真正的汽车,只是你的一份设计规划,后续你交付给工厂,工厂按照你的设计蓝图,生产出了一辆汽车,这就是实例化,后续工厂有根据你的蓝图设计了一条流水线,每一辆从流水线上生产下来的车辆,都是里这个蓝图(类)的一个对象,他们都有蓝图定义的属性和功能。在C++中类就充当着蓝图的作用,它定义了对象拥有哪些属性,那么就和我一起来揭开这份“蓝图”的面纱吧。 1.类 1.1.类的定义 类的基本思想是数据抽象和封装,数据抽象是一种依赖于接口和实现的分离式编程技术,类的接口包括用户所能执行的操作,类的实现则是包括类的数据成员、负责接口实现的函数以及定义类所需的各种私有函数。封装实现了类的接口和实现的分离,封装后的类隐藏了他的视线细节,也就是说,

By Ne0inhk
深入解剖STL RB-tree(红黑树):用图解带入相关复杂操作实现

深入解剖STL RB-tree(红黑树):用图解带入相关复杂操作实现

👇点击进入作者专栏: 《算法画解》 ✅ 《linux系统编程》✅ 《C++》 ✅ 文章目录 * 一、红黑树介绍 * 1. 什么是红黑树? * 2. 红黑树的规则 * 3. 为什么最长路径不超过最短路径的两倍? * 4. 红黑树的效率 * 二、红黑树的实现 * 2.1 红黑树的节点结构 * 2.2 红黑树整体结构 * 三、红黑树的插入操作 * 3.1 插入的大致流程 * 3.2 插入后的三种情况 * 情况1:叔叔节点存在且为红色(变色处理) * 情况2:叔叔节点不存在或为黑色 + cur和p在同一侧(单旋+变色) * 情况3:叔叔节点不存在或为黑色 + cur和p在不同侧(双旋+变色) * 3.3 插入完整代码 * 3.4 旋转操作的实现

By Ne0inhk
(最新原创毕设)微信小程序学习打卡系统/01.22(白嫖源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案

(最新原创毕设)微信小程序学习打卡系统/01.22(白嫖源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案

摘  要 随着学习任务日益增多,学习者常因缺乏有效的激励和管理手段而难以坚持学习。传统学习方式缺乏互动性和监督,影响学习效率。因此,开发一个基于微信小程序的学习打卡系统,旨在通过设定学习目标、打卡任务和奖励机制来激励学习者,帮助他们养成持续学习的好习惯。本系统分为管理员和用户两大模块,管理员可管理用户信息、学习资源、打卡计划、奖励规则等;用户则可浏览学习资源、设定打卡计划、记录学习进度、参与社交互动等,形成良好的学习氛围。 系统采用Java语言,基于SpringBoot框架进行后端开发,前端使用微信小程序,数据库则使用MySQL进行数据存储。通过RESTful API实现前后端分离,提升系统的灵活性和可扩展性。管理员可以实时查看用户学习数据和进度,优化学习资源和奖励规则,提升平台的管理效率。 通过学习打卡系统用户能在规定的学习计划下高效完成学习任务,并通过奖励激励机制增强学习动力,形成良好的学习习惯;管理员可以高效管理平台资源和用户,提供个性化的学习建议,最终达到提升学习效率、促进知识积累的目的。 关键词:学习打卡系统;Java语言;Spring Boot框架;微信小程序;My

By Ne0inhk
C++ 多线程同步之互斥锁(mutex)实战

C++ 多线程同步之互斥锁(mutex)实战

C++ 多线程同步之互斥锁(mutex)实战 💡 学习目标:掌握 C++ 标准库中互斥锁的基本用法,理解多线程同步的核心原理,能够解决多线程环境下的资源竞争问题。 💡 学习重点:std::mutex 与 std::lock_guard 的使用、死锁的产生原因及规避方法、实际场景中的同步案例实现。 48.1 多线程同步的必要性 在多线程编程中,当多个线程同时访问共享资源时,会出现资源竞争问题。 例如两个线程同时对同一个变量进行读写操作,会导致最终结果与预期不符。 这种问题被称为线程安全问题,而解决该问题的核心就是线程同步。 ⚠️ 注意事项:线程不同步会引发数据竞争,造成程序运行结果不可预测,甚至导致程序崩溃。 举个简单的反例,两个线程同时对全局变量 count 进行自增操作: #include<iostream>#include<thread>usingnamespace std;int count

By Ne0inhk