一文教会你Java中的异常处理
1、错误和异常
- 异常:就指的是程序在执行过程中,出现的非正常情况,最终导致JVM非正常停止。
- 异常体系如图:
Error: 严重错误问题,无法处理的错误,只能事先避免,比如内存溢出
Exception:称为异常类,它表示程序本身可以处理的问题,比如数组下标越界
2、异常分类
- 编译时异常:也称为检查异常,必须显示处理,否则程序就会发生错误,无法通过编译。
- 运行时异常也称为非检查异常,无需显示处理,也可以和编译时异常一样处理。!
RuntimeException:RuntimeException所有的类及其子类被称为运行时异常,其他的异常都是编译时异常。RuntimeException在编译期是不检查的,出现问题后会抛出异常,需要修改代码进行解决。
非RuntimeException:非RuntimeException编译期就必须处理,否则程序不能通过编译。
3、异常处理机制
- 当程序中抛出一个异常后,从程序中导致异常的代码处跳出,java虚拟机检测寻找和try关键字匹配的处理该异常的catch块;
- 如果找到,将控制权交到catch块中的代码,然后继续往下执行程序,try块中发生异常的代码不会被重新执行;
- 如果没有找到处理该异常的catch块,最终运行时报错;
- 代码格式:
try {
可能出现异常的代码;
}catch(异常名1 变量名1){
异常的处理代码;
}catch(异常名2 变量名2){
异常的处理代码;
}
- 执行流程
- 程序从try里面的代码开始执行;
- 出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统;
- 当运行时系统接收到异常对象时,会到catch中去找匹配的异常类,找到后进行异常的处理;
- 执行完毕之后,程序还可以继续往下执行。
- 每个try语句块可以伴随一个或多个catch语句,用于处理可能产生的不同类型的异常;
- 捕获的异常类型由上至下的捕获异常类型的顺序应是子类到父类的。
4、finally 块
- finally语句为异常处理提供的一个统一的出口,使得在控制流程到程序其它部分之前,能够对程序的状态作统一的管理;
- 无论try所指的程序块中是否抛出异常,finally所指定的代码都要被执行;
- 通常finally在语句中可以进行资源的释放工作,如关闭打开的文件,关闭数据库连接等;
- 语法格式如下:
try {
可能出现异常的代码;
} catch(异常名 变量名){
异常的处理代码;
}finally {
必须执行的代码;
}
5、throws 和throw关键字
throws: 程序中会声明很多方法,这些方法中可能会因某些错误而引发异常,但不希望直接在这个方法中处理这些异常,而希望调用它的方法统一处理,这时候就需要使用"throws"关键字声明在这个方法上抛出异常。
throw: 当程序发生错误而无法处理的时候,会抛出对应的异常对象,除此之外,在某些时候,想要自行抛出异常,此时需要用到"throw"”关键字,并生成指定的异常对象后抛出。throw定义在方法内,用来抛出一个异常对象。
throws和throw的区别:
throws | throw |
---|---|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示抛出异常,由该方法的调用者来处理 | 表示抛出异常,由方法体内的语句处理 |
表示出现异常的一种可能性,并不一定会发生这些异常 | 执行throw—定抛出了某种异常 |
6、子类和父类构造函数中使用throws 关键字
(1)父类构造函数中使用throws抛出编译时异常
子类构造方法中throws抛出的异常必须大于等于父类throws抛出的异常,并且只能抛出不能捕获。
(2)父类构造函数中使用throws抛出运行时异常
当父类构造函数中throws抛出运行时异常,子类构造方法中可以声明异常也可以不声明异常,如果声明,子类构造函数中抛出的异常要大于或者等于父类中抛出的异常。
7、方法重写中使用throws 关键字
(1)使用继承时,在父类某个方法上声明了异常,子类重写这个方法时:
-
不处理异常(重新定义时不设定throws);
-
可仅throws父类方法中声明的部分异常;
-
子类throws抛出的异常小于或者等于父类throws抛出的异常;
(2)子类重写父类该方法时抛出运行时异常,那么父类被重写的方法上可以不抛出异常
(3)如果父类方法没有抛出异常,子类重写父类该方法时抛出编译异常,那么子类重写的方法会报编译错误,此时解决办法有两种:
- 父类被重写的方法上抛出的异常要大于或者等于子类方法上抛出的异常
- 子类方法中直接捕获异常,不抛出
8、RuntimeException和自定义异常类
(1)RuntimeException类
RuntimeException类属于非检查异常,因为普通ⅣVM操作引起得运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在java应用程序中会频繁出现。因此它们不受编译期检查与处理或者声明规则的限制。
(2)常见 RuntimeException
- NullPointerException:当应用程序试图在需要对象的地方使用null时,抛出该异常
- ArrayIndexOutOfBoundsException:当使用的数组下标超出数组允许范围时,抛出该异常
- ClassCastException:当试图将对象强制转换为不是实例的子类时,抛出该异常
- NumberFormatException:当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当的格式时,抛出该异常
(3)Exception常用API
printStackTrace:Throwable定义了一个方法可以输出错误信息,用来跟踪异常事件发生时执行堆栈的内容,该方法定义为void printStackTrace();
getMessage:Throwable定义了一个方法可以得到有关异常事件的信息,该方法定义为String getMessage();
(4)自定义异常类
异常机制可以保证程序更安全和更健壮。虽然类库已经提供很多可以直接处理异常的类,但是有时候为了更加精准地捕获和处理异常以呈现更好的用户体验,需要开发者自定义异常。
自定义异常的格式:
public class 自定义异常类名 extends Exception {
无参构造
有参构造
}
9、垃圾回收机制
(1)垃圾回收机制
―垃圾回收机制简称GC是VM自带的一个线程,用于回收没有任何引用指向的对象-程序员不用担心内存管理,因为垃圾收集器会自动进行回收管理,一般情况下,当我们需要GC线程即刻回收无用对象时,可以调用System.gc()方法System.gc()用于建议虚拟机马上调度GC线程回收资源,具体的实现由的JVM决定。
(2)finalize()
finalize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用。
(3)内存泄漏
不再使用的内存没有被及时回收,严重的内存泄漏会因过多的内存占用而导致程序的崩溃;GC线程判断对象是否可以回收的依据是该对象是否有引用指向,因此,当确定该对象不再使用时,应该及时将其引用设置为null。
- 点赞
- 收藏
- 关注作者
评论(0)