在编程语言中,异常定义了程序中遇到的非致命的错误,比如,程序要打开一个不存的文件、网络连接中断、除零操作、操作数越界、装载一个不存在的类等情况。这些异常错误往往会导致程序中断,无法正常执行。异常处理机制可以防止程序在出现异常时直接崩溃。它可以让程序继续执行,并且处理相应的错误(比如:打印出错误信息等)。今天我们就来看一下JAVA的异常处理机制。
一、基本格式
try {
//可能产生异常的代码部分
//捕获异常
} catch (Exception e) {
//对获取的异常信息进行处理
}finally{
//异常部分以外的代码
}
二、处理流程
A.没有出现异常时。只有catch中的代码不会被执行,其他部分的代码都会被执行。
测试代码:
package abnormalTest;
import java.io.IOException;
//定义一个测试类,检查JAVA中的异常处理机制
public class Test {
int age;
public void Abnormal(){
try {
System.out.println("执行try内部异常发生前代码块");
int i=1;
int x=5/i;
System.out.println("执行try内部异常发生后代码块");
} catch (Exception e) {
System.out.println("执行catch内部代码块");
}finally{
System.out.println("执行finally内部代码块");
}
System.out.println("执行其他的代码块");
}
//主函数入口
public static void main(String[] args) {
Test t=new Test();
t.Abnormal();
}
}
测试结果
B.try中代码出现异常时。catch部分代码会被执行,进行异常的处理。而try中发生异常之后的代码都不会被执行。
代码部分把i的值改成0以后重新运行,结果如下:
三、小结:
(1)当发生异常的时候,在try代码块中捕捉异常,异常代码发生行之后的代码不再运行。
(2)只有当try代码块发生异常的时候,才会执行到catch代码块。
(3)不管try中是否发生异常,finally代码块和try…catch...finally以外的代码块都会执行(当有return关键字的时候,这两个代码块的执行情况还有所不同,后面会讲到)。
不过当代码中出现System.exit(0)时需要格外小心,以下两种情况都会导致finally和try…catch...finally以外的代码块无法执行:
A.try中不发生异常时,try块中有System.exit(0);
B.try中发生异常时,catch中有System.exit(0);
补充:System.exit(0)是退出虚拟机的语句,可以视为强制终止程序的指令。
四、附上一道面试题
求下面函数的运行结果
//测试return方法
public int TestReturn() {
try {
return 1;
} catch (Exception e) {
return 2;
}finally{
return 3 ;
}
}
运行结果:
分析:try中没有异常,因此会先执行return 1,不会执行catch部分的代码return2;然后继续执行finally部分的代码return 3。最后程序返回3。有人可能会不理解,明明return就是返回了,为何还会继续执行catch和finally部分的代码块。这里我们可以粗浅地理解为try...catch...fianlly本身设置的一种处理机制。不管有没有异常,除非程序被强制终止,否则finally是一定要进去的。因此最后的返回值以finally里面的为准。而如果在try、catch或者finally中执行了return语句,try...catch...finally以外的代码块则不会再被执行。
从Java虚拟机的角度来看:return指令分为两条字节码指令laod和ireturn,其中ireturn语句必须在整个方法中需要执行的代码都执行完了他才能执行。首先执行try部分的代码return 1中的iload部分,先把1这个数放到操作数栈顶。然后进入finally部分,执行return 3,同样地,把3放到操作数栈顶,覆盖原来的1。此时JVM发现TestReturn方法中所有需要执行的代码块都已经执行完毕了,于是就执行ireturn。最终返回3。
测试代码如下:
Unreachable code的报错信息说明31行是一段永远不会执行到的代码.因为不管程序有没有出现异常,都会先执行到return 语句,退出TestReturn 方法。因此如果我们有一部分代码需要在异常处理完之后继续执行,最后把它放到finally里面。