目录
1.异常的背景
初识异常
异常其实已经是我们的老朋友了,相比大家在打代码时都遇到过这样的情况吧!
所谓异常就是在程序运行时出现错误时通知调用者的一种机制,异常的种类有很多,不同的异常有不同的处理方式。
异常的好处
将错误代码与常规代码分开,更容易理解代码,具体用法见下文。
2.异常的基本用法
捕获异常
基本语法:
try {
有可能出现异常的语句;
} [catch (异常类型,异常对象) {
出现异常后的处理行为;
}...]
[finally {
异常的出口
}]
- try代码块中放的是可能出现异常的代码
- chath代码块中放的是出现异常后的处理行为
- finally代码块中的代码用于处理善后工作,放在最后
- 其中catch和finally都可以根据情况选择加或不加
代码示例1:不处理异常
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println("before");
System.out.println(arr[100]);
System.out.println("after");
}
执行结果:
我们发现一旦出现异常程序就终止了,"after"没有正常打印。
代码示例2 :使用try catch后的程序执行过程
public static void main(String[] args) {
int[] arr = {1,2,3};
try {
System.out.println("before");
System.out.println(arr[100]);
System.out.println("after");
} catch (ArrayIndexOutOfBoundsException e) {
//打印出异常的调用栈
System.out.println("捕捉到数组越界异常!");
}
System.out.println("after try catch");
}
执行结果:
我们发现,一旦try中的代码出现异常,那么try代码块的程序就不会继续运行,而是交给catch中的代码来执行,catch执行完毕会继续往下执行。
代码示例3:finally表示最后的善后工作,比如释放资源
public static void main(String[] args) {
int[] arr = {1,2,3};
try {
System.out.println("before");
arr = null;
System.out.println(arr[100]);
System.out.println("after");
} catch (Exception e) {
System.out.println("出现了异常!");
} finally {
System.out.println("finally code");
}
}
执行结果:
无论是否出现异常,finally中的代码一定会执行到。
异常处理流程
- 程序先执行try中的代码
- 如果try中的代码出现异常,就会结束try中的代码,看和catch中的异常类型是否匹配
- 如果找到匹配的异常类型,就会执行catch中的代码
- 如果没有找到匹配的异常类型,就会将异常向上传递到上层调用者
- 无论是否找到匹配的异常类型,finally中的代码都会被执行(在该方法结束之前)
- 如果上层调用者也没有处理了异常,就继续向上传递
- 一直到main方法也没有合适的代码处理异常,就会交给JVM进行处理,此时程序就会异常终止
抛出异常
除了Java内置的类会抛出一些异常之外,我们也可以手动抛出某个异常,使用throw关键字完成这个操作。
public static int divide(int x, int y) {
if (y == 0) {
throw new ArithmeticException("抛出除 0 异常");
}
return x / y;
}
public static void main(String[] args) {
System.out.println(divide(10,0));
}
执行结果:
异常说明
我们在处理异常的时候,通常希望直到这段代码中会出现哪些可能的异常,我们可以使用throws关键字,把可能抛出的异常显示标注在方法定义的位置,从而提醒调用者要注意捕获这些异常。
public static int divide(int x, int y) throws ArithmeticException {
if (y == 0) {
throw new ArithmeticException("抛出除 0 异常");
}
return x / y;
}
关于finally的注意事项
finally中的代码保证一定会执行到,但这也会带来一些麻烦。
public static int func() {
try {
return 10;
} finally {
return 20;
}
}
public static void main(String[] args) {
System.out.println(func());
}
fifinally
执行的时机是在方法返回之前
(try
或者
catch
中如果有
return
会在这个
return
之前执行
fifinally)。
但是如果 fifinally 中也存在
return
语句
,
那么就会执行
fifinally
中的
return,
从而不会执行到
try
中原有的
return。