例
public class Test {
public static void main(String[] args) {
int s1 = f1();
System.out.println(s1);
StringBuffer s2 = f2();
System.out.println(s2);
}
private static StringBuffer f2() {
StringBuffer sb = new StringBuffer("hello ");
try {
return sb;
} catch (Exception e) {
return null;
}finally{
sb.append("world");
System.out.println("f2");
}
}
private static int f1() {
int res =1;
try {
res = 2;
return res;
} catch (Exception e) {
return 0;
}finally{
res = 3;
System.out.println("f1");
}
}
}
输出结果
f1
2
f2
hello world
原因
在捕获异常并处理的代码中,执行过程是:
- 先执行try中的代码块
- 发生异常执行catch中代码块,不发生不执行
- 接着执行finally中的代码块
注意:
若在try,catch和finally中的代码块均含有retrun,则执行过程为:
首先执行try中的代码块:
a. 若没有发生异常并遇到return时,则拷贝当前要返回的数据(基本类型拷贝值,引用类型拷贝引用),然后执行finally中的代码块;
若finally中没有retrun时,返回try中拷贝的数据;若有,则finally中的return覆盖try中的retrun,返回新的数据的拷贝。b. 若发生异常,则执行catch中的代码块,无视try中的return,执行完若遇到return,则拷贝数据,执行finally中代码块;finally中代码块执行完时若没有遇到return,则返回catch中拷贝的数据,若遇到则返回finally中return的语句,即发生return覆盖
总结:
- 程序先执行try中代码块。
- 发生异常执行catch中代码块,不发生不执行
- 接着执行finally中的代码块
- 在执行过程中:
a. 若遇到retrun返回时,会发生retrun覆盖现象。(优先级:finally >catch>try)
b. 步骤23能够执行的前提条件是在try中没有如5/0,System.exit(0/1)强制退出的语句。
例:
return 覆盖:
public class Test {
public static void main(String[] args) {
int s1 = f1();
System.out.println(s1);
StringBuffer s2 = f2();
System.out.println(s2);
}
private static StringBuffer f2() {
StringBuffer sb = new StringBuffer("hello ");
try {
return sb;
} catch (Exception e) {
return null;
}finally{
sb.append("world");
System.out.println("f2");
}
}
private static int f1() {
int res =1;
try {
res = 2;
if (res == 2) {
throw new Exception();
}
return res;
} catch (Exception e) {
return 0;
}finally{
res = 3;
System.out.println("f1");
return res;
}
}
}
结果:
f1
3
f2
hello world
补充一点:
一个 try 块可能有多个 catch 块。若如此,则执行第一个匹配块。即Java虚拟机会把实际抛出的异常对象依次和各个catch代码块声明的异常类型匹配,如果异常对象为某个异常类型或 其子类的实例,就执行这个catch代码块,不会再执行其他的 catch代码块