文章目录
Java异常概述
Java中异常机制可以使程序中的异常处理代码和正常业务代码分离,保证程序代码更加油压,并可以提高程序的健壮性。
Java的异常机制主要依赖于try、catch、finally、throw和throws五个关键字。
异常体系和分类
Java提供了丰富的异常类,这些异常类之间有严格的继承关系,如下图(常见异常)
- java把所有的非正常情况分成两种:
- 异常(Exception)
- 错误(Error)
它们都继承自Throwable父类
- Error错误,一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误等,这种错误无法恢复或不可能捕获,将导致应用程序中断。
- Exception异常,产生后可以进行捕获,通过代码的方式进行纠正,使得程序能够继续运行。
异常处理机制
使用try…catch捕获异常
- 捕获异常:Java中对异常有针对性的语句进行捕获,可以对出现的异常进行制定方式的处理
捕获异常语法如下:
try{
//可能会出现异常的代码
...
}catch(异常类型 e){
处理异常的代码
}
- 如果执行try块里的业务逻辑代码时出现异常时,系统自生成一个异常对象,该异常被提交给java运行环境,这个过程称为抛出(throw)异常。
- 当Java运行环境收到异常对象时,会寻找处理该异常对象的catch块,如果找到合适的,就交给该catch块执行,这个过程称为捕获(catch)异常
使用throw抛出异常
- Java允许程序自行抛出异常,可以使用throw关键字在指定的方法中抛出指定的异常
- throw语句抛出的不是异常类,而是一个异常实例,而且每次只能抛出一个异常实例,其语法格式:
throw new xxxException(“异常产生的原因”);
【注意】
- throw关键字必须写在方法的内部
- throw关键字后new的对象必须是Exception或者Exception的子类对象
- throw关键字抛出指定的异常对象,必须处理这个异常对象
- 若throw后面创建的是RuntimeException或者是其子类对象,可以不处理,默认交给JVM处理
- 若throw后面创建的是编译异常,必须处理,要么throws,要么try…catch
使用throws声明抛出异常
使用throws声明抛出异常的思路是,当前方法不知道如何处理这种类型的异常,该异常有上一级调用者处理;如果main方法也不知道如何处理,也可以使用throws声明抛出异常交给JVM处理,JVM打印异常的跟踪栈信息,并中止程序运行。
- throws声明抛出的语法格式仅限跟在方法签名之后。
- throws关键字后面声明的异常必须是Exception或者其子类
- 方法内部如果抛出多个异常对象,throws后面必须声明多个异常,用逗号隔开
- 如果抛出的多个异常对象有子父类关系,直接声明父类异常即可
- 调用了一个声明抛出异常的方法,必须处理声明的异常
- 要么继续使用throws声明抛出,要么try…catch自己处理
Throwable类中的3个异常处理方法
- String getMessage() 返回此throwable的简短描述
- String toString() throwable的详细消息字符串
- void printStackTrace() JVM打印异常对象,默认此方法,打印的异常信息是最全面的
finally代码块
有些时候,程序在try块里面打开了一些物理资源(比如数据库连接、网络连接和磁盘文件等),这些物理资源都必须显式回收。为了保证一定能回收catch块中的资源,异常处理机制提供了finally块。
- finally不能单独使用,必须和try一起使用
- finally一般用于资源回收(资源释放),无论程序是否出现异常,都要执行
- 尽量避免在finally中使用return或throw等导致方法终止的语句
多异常捕获
- 多个异常分别处理
- 多个异常一次捕获,多次处理
- 多个异常一次捕获,一次处理
- catch里边定义的异常变量,如果有子父类关系,子类的异常变量必须写在上面
子父类异常注意
- 如果父类抛出了多个异常,子类重写父类方法时,抛出和父类相同的异常或者父类异常的子类或者不抛出异常,且不能比父类方法声明抛出的异常多
- 父类方法没有抛出异常,子类重写父类该方法时也不可能抛出异常,此时子类产生该异常,只能捕获处理,不能声明抛出
自定义异常
- java提供的异常类,不够我们使用,需要自己定义一些异常类
【格式】
public class XXXException extends Exception | RuntimeException{
添加一个空参数的构造方法
添加一个带异常信息的构造方法
}
- 自定义异常类一般都是以Exception结尾,说明该类是一个异常类
- 自定义异常类必须继承Exception或者RuntimeException
- 继承Exception:那么自定义异常类就是一个编译期异常,如果方法内部抛出了编译期异常,就必须处理,throws或try…catch
- 继承RuntimeException :自定义异常类就是运行期异常,无需处理,交给虚拟机处理(中断处理)
/**
自定义异常类:
*/
public class RegisterException extends Exception {
//添加一个空参数的构造方法
public RegisterException(){
super();
}
/*
添加一个带异常信息的构造方法
查看源码发现,所有的异常类都会有一个带异常信息的构造方法,方法内部会调用父类带异常信息的构造方法,让父类来处理异常信息
*/
public RegisterException(String message){
super(message);
}
}