目录
1. 异常概述
1.1 什么是异常?
Java中的异常是指程序运行时出现错误或者异常情况,导致程序无法继续执行的现象
例如:数组下标越界异常,空指针异常,类型转换异常都属于异常情况
1.2 异常机制在Java中有什么作用?
(1)Java提供了异常处理机制,即在程序中对可能出现的异常情况进行捕捉和处理。异常机制可以帮助程序员更好的管理程序的错误和异常情况,避免程序出现难以预测的行为
(2)没有异常处理机制的话,程序就可能出现一些难以预测和难以调试的异常行为,可能导致程序崩溃,甚至造成数据损失,损害用户利益,因此,异常机制是一项非常重要的功能,是编写可靠程序的基础
2. 异常的继承结构
2.1 概述
(1)所有异常都继承了Throwable类,都是可抛出的
(2)Error是无法处理的,如果出现只有一个结果:JVM终止
(3)Exception是可以处理的
(4)异常的分类
1.所有的RuntimeException类的子类,这种异常也叫做运行时异常, 非受控异常, 未检查异常(UncheckedException)
2.Exception的子类(除RuntimeException外),这种异常也叫做编译时异常, 受控异常,检查异常(CheckedException)
注意:编译时异常并不是编译阶段发生的异常,所有的异常都是运行阶段发生的!!!
之所以叫编译时异常是因为这种异常在编译阶段必须预先处理,否则编译器会报错!!! 因此得名叫做编译时异常
(5)运行时异常特点:可以选择预处理,也可以不进行处理,没有硬性要求
(6)编译时异常特点:必须在编译阶段进行处理,如果不处理,编译器报错
(7)运行时异常一般由程序员的错误引起
(8)编译时异常一般由外部环境或外在条件引起
2.2 继承结构图
3. 异常的发生
3.1 异常的产生
当Java程序运行时,如果遇到了某些特定的错误(如空指针引用,数组下标越界等),JVM会识别这些错误,并判断它们是否符合Java中定义的异常条件
3.2 异常对象的创建
如果错误符合某个异常条件,JVM就会在底层创建一个该异常对应的异常对象,这个对象包含了关于异常的信息,如异常的类型,异常的调用栈信息以及可能的错误描述(message)等
3.3 异常的抛出和捕捉
异常对象创建后,JVM会将其抛出,即中断当前方法的执行流程,并将异常对象传递给调用栈的上一层,这会一直持续到找到能够处理该异常的代码块为止
如果在调用栈的任意一层找到了能处理该异常的catch块,JVM就会将异常对象传递给该catch块,并执行其中的异常处理代码。如果JVM没能找到能够处理该异常的catch块,程序就会终止执行,并显示一个错误信息
4. 如何自定义异常
第一步:编写子类继承RuntimeException类或者Exception类
第二步:提供两个构造方法,一个无参构造,一个带有参数String message的构造方法,并在此构造方法中调用super(message)
注意:自定义异常需要手动触发并抛出
5. 预处理异常的两种方式
5.1 throws
throws关键字抛出 方法可能发生的异常, 抛给上一层调用者
这一方法中 throws抛出的异常, 上一层调用者抛出的异常中必须也有
如果都选择throws,那么最后JVM的默认异常处理机制将会介入
JVM会干两件事:1.打印异常的堆栈追踪信息 2.程序终止
5.2 try{}catch(){}
5.2.1 语法格式
try{
}catch(异常类型){
}catch(异常类型){
}catch(异常类型){
}
5.2.2 注意事项
try块里需要写可能发生异常的代码
try块里的异常一旦发生,那么就会中断try块中的后续代码执行
异常发生后,会把发生的异常对象传给catch括号里的异常变量,所以catch括号里的变量的值不是null
catch块中捕捉的异常 应按照异常的继承关系 遵循从小到大的原则,即子类异常在前,父类异常在后
5.2.3 Java7新特性
在Java7之前,每个catch块最多只能捕获一个异常类型。但在Java7及之后的版本,可以在单个catch块中使用竖线|来指定多个异常类型,从而在一个catch块中捕获多个类型
6.异常常用的方法
6.1 getMessage()方法
获取通过构造方法创建异常对象时传递的参数信息
6.2 printStackTrace()方法
打印异常的堆栈追踪信息
打印的异常信息是符合栈数据结构的
7.finally语句块
finally语句块中的代码是一定执行的
finally语句块至少需要配合try块一起使用:
try{}finally{}或者
try{}catch(){}finally{}
7.1finally语句块的作用
通常在finally语句块中进行资源的释放
资源释放的工作比较重要,如果资源没有释放就会一直占用内存
为了保证资源的释放,也就是说,不论异常是否发生,释放资源的代码一定要保证执行
因此通常在finally语句块中进行资源的释放
7.2 注意事项
(1)
在以上示例中, return之前 finally的代码会执行
(2)
在以上示例中,finally块中的代码不会执行