Java中的异常体系
在开发过程中难免会遇到各种各样的异常,如何处理异常直接影响程序或系统的稳定性,有时在线上仅仅忘记处理一个空指针异常都有可能引起整个项目的崩溃,所以了解开发中的异常是至关重要的!
概念
异常通常是指某个方法不能按照正确的方式完成时,可以通过抛出异常的方式退出该方法,在异常中封装了方法执行过程中的错误信息及原因,然后调用方在获取该异常后可根据业务的情况选择处理异常或者继续抛出该异常。
在方法执行过程中出现异常时,Java异常处理机制会将代码的执行权交给异常处理其,异常处理器根据在系统中定义的异常处理规则执行不同的异常处理逻辑(抛出异常或捕捉处理异常)
异常分类
在Java中,Throwable是所有错误或异常的父类,又可以分为Error和Exception,常见的如下图所示。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-usdIYg7z-1636088792745)(https://i.bmp.ovh/imgs/2021/11/72c136eb9427e098.png)]
Error 指Java程序运行错误,如果程序在启动时出现Error,则启动失败;如果程序运行过程中出现Error,则系统将退出程序。出现Error是系统的内部错误或资源耗尽,Error不能在程序运行过程中被动态处理,一旦出现Error,系统能做的只有记录错误的原因和安全终止。
Exception 指 Java程序运行异常,在运行中的程序发生了程序员不期望发生的事情,可以被Java异常处理机制处理。Exception也是程序开发中异常处理的核心,可分为RuntimeException(运行时异常)和CheckedException(检查异常),如下图所示
-
RuntimeException(运行时异常):指在Java虚拟机正常运行期间抛出的异常,RuntimeException可以被捕获并处理,如果出现此情况,我们需要抛出异常或者捕获并处理异常。常见的有NullPointerException、ClassCastException、ArrayIndexOutOfBoundsException等
-
CheckedException(检查异常):指在编译阶段Java编译器检查CheckedException异常,并强制程序捕获和处理此类异常,要求程序在可能出现异常的地方通过try catch语句块捕获异常并处理异常。常见的有由于I/O错误导致的IOException、SQLException、ClassNotFoundException等。该类异常通常由于打开错误的文件、SQL语法错误、类不存等引起。
异常处理方式
异常处理方式有抛出异常和使用try catch语句块捕获异常两种方式。
(1)抛出异常:遇到异常时不进行具体的处理,直接将异常抛给调用者,让调用者自己根据情况处理。抛出异常的三种形式:throws、throw和系统自动抛出异常。其中throws作用在方法上,用于定义方法可能抛出的异常;throw作用在方法内,表示明确抛出一个异常。
//2: 使用throws在方法上抛出异常
public static void main(String[] args) throws Exception {
String str = "hello world";
int index = 10;
div(10,0);
if(index >= str.length()){
//1:使用throw 在方法内抛出异常
throw new StringIndexOutOfBoundsException();
}else {
str.substring(0,index);
}
}
public static void div(int a,int b) {
System.out.println(a/b);
}
(2)使用try catch捕获并处理异常:使用费try catch 捕获异常能够有针对性的处理每种可能出现的异常,并在捕获到异常后根据不同的情况做不同的处理。其使用过程比较简单:用try catch语句块将可能出现异常的代码抱起来即可。
try{
//具体的业务逻辑实现
}catch (Exception e){
//捕获异常并处理
}
throw 和 throws的区别
-
位置不同:throws作用在方法上,后面跟的是异常的类,而throw作用在方法内,后面跟的是异常的对象。
-
功能不同:throws用来声明方法在运行中可能出现的异常,以便调用者根据不同的异常类型预先定义不同的处理方式;throw用来抛出封装了异常信息的对象,程序在执行到throw时后序的代码将不再执行,而是跳转到调用者,并将异常信息抛给调用者。也就是说throw后面的语句块将无法被执行(finally语句块除外!)
面试问题
记得在微博一面的时候面试官就问了我这个Java异常体系中的问一个demo问题,如下所示:
public void test01() {
int i = 1;
int divid = 0;
try {
int n = i / divid;
System.out.println("走的try:"+0);
} catch (Exception e) {
System.out.println("走的catch:"+1);
//return returnSttat(i);
} finally {
System.out.println("走的finally:"+2);;
}
}
在异常的情况下会输出什么呢?
比如上面给出的i = 1,divid = 0; 此时i/divid = 1/0 是不允许的!
所以会捕获异常,也就是会走catch,因此会输出:走了catch:1
最后的finally不管是否异常都会走,所以同时也会输出:走了finally:2
总的输出是:
走的catch:1
走的finally:2
在正常的情况下会输出什么呢?
比如给出 i=4,divid = 2;此时i/divid = 4/2 是允许的!
所以不用捕获异常,也就是会走try,因此会输出:try:0
最后的finally不管是否异常都会走,所以同时也会输出:走了finally:2
走的try:0
走的finally:2
推荐阅读