不管是在Java还是其他开发语言中,异常处理都是非常重要的部分。异常处理大大提高了我们代码的健壮性。下面我们就来学习一下Java中的异常处理机制。
一、异常的定义及分类
定义:我们的java程序也是会存在某些不正常 的情况的,这些不正常的 情况我们就统称异常。
说起异常,你第一个想到的是不是Exception呢?其实异常远远比一个Exception类要复杂的多。Exception也不是异常的最大的父类。
看一下异常的分类
Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类。
Error(错误):是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行的操作无关,而表示代码运行时 JVM(Java 虚拟机)出现的问题。
Exception(异常):是程序本身可以处理的异常。 Exception 类有一个重要的子类 RuntimeException。RuntimeException 类及其子类表示“JVM 常用操作”引发的错误。例如,若试图使用空值对象引用、除数为零或数组越界,则分别引发运行时异常(NullPointerException、ArithmeticException)和 ArrayIndexOutOfBoundException。
二、异常处理机制
1.抛出异常
抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。
(1)throws抛出异常throws语句用在方法定义时声明该方法要抛出的异常类型。如果抛出的是Exception异常类型,则该方法被声明为抛出所有的异常。多个异常可使用逗号分割。方法抛出异常后,抛向调用该方法的方法,由他去处理。
public SearchResult search(SolrQuery solrQuery) throws Exception {}
(2)throw抛出异常
throw总是出现在函数体中,用来抛出一个Throwable类型的异常。程序会在throw语句后立即终止,它后面的语句执行不到,然后在包含它的所有try块中(可能在上层调用函数中)从里向外寻找含有与其匹配的catch子句的try块。
public void test(int y) throws Exception {
if (y < 0) { // 判断参数是否小于0
throw new Exception ("异常"); // 异常信息
}
}
2.捕获异常
捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适 的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。
(1)try-catch语句
try {
// 可能会发生异常的程序代码
} catch (Type1 id1){
// 捕获并处置try抛出的异常类型Type1
}
catch (Type2 id2){
//捕获并处置try抛出的异常类型Type2
}
关键词try后的一对大括号将一块可能发生异常的代码包起来,称为监控区域。Java方法在运行过程中出现异常,则创建异常对象。将异常抛出监控区域之 外,由Java运行时系统试图寻找匹配的catch子句以捕获异常。若有匹配的catch子句,则运行其异常处理代码,try-catch语句结束。
(2)try-catch-finally语句
try {
// 可能会发生异常的程序代码
} catch (Type1 id1) {
// 捕获并处理try抛出的异常类型Type1
} catch (Type2 id2) {
// 捕获并处理try抛出的异常类型Type2
} finally {
// 无论是否发生异常,都将执行的语句块
}
try 块:用于捕获异常。其后可接零个或多个catch块,如果没有catch块,则必须跟一个finally块。catch 块:用于处理try捕获到的异常。
finally 块:无论是否捕获或处理异常,finally块里的语句都会被执行。
三、异常中的状态码
一开始学习对异常这块并没有很重视,工作中才发现异常处理真的非常重要,好的异常处理不仅可以帮助我们快速的开发调bug,也是一种良好的编码习惯。
在工作中的对于状态码的管理还是很重要的。下面介绍一下遇到过的异常码定义。
public enum ServerStatus {
SUCCESS("0000","成功"),
UNKNOW_ERROR("1000","服务器繁忙"),
USER_DEFINITION("1002","用户名或密码错误"),
USER_REGISTER("1003","用户未注册"),
MENU_NAME_REPEAT("1004","菜单名称重复"),
QRCODE_INVALID("1005","二维码失效"),
QRCODE_CHECKING("1006","扫描完成,正在处理"),
USER_TOKEN_FAILURE("1007","无效的token"),
ADD_RECORD_EXIST("1008","记录已经存在,无法重复添加"),
}
当然,这些都是自己定义的。我们通过返回的状态码就可以清楚的知道是什么问题。
小结:异常处理并不仅仅是我们try catch throw就可以的。还是要我们在工作中慢慢体会他的用法和好处。