try catch finally执行顺序
public void tryFinally(){
try {
tryIt();
} catch (Exception e) {
handle();
} finally {
wrap();
}
}
对应字节码:
变量表:
异常表:
解释:注意EndPC不包括所指行,[Start PC,End PC)
异常测试:
public static void test(){
try {
System.out.println(1/0);
} catch (Exception e) {
int[] arr = new int[1];
arr[9] = 9;//
} finally {
}
}
//结果:
//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 9
通过字节码的展示,易知:
-
try无异常,执行try与finally内容
-
try出现待捕获的异常,则执行catch与finally,如果catch也出现异常,则执行finally,并抛出catch中的异常
-
try出现其他未捕获的异常,执行finally,并抛出异常
-
如果finally本身出现异常,则finally语句块停止运行,tryFinally方法异常退出,并把异常抛给tryFinally方法的调用者
try { return A }catch{ }finally{ }情况
public int test(){
int a = 9;
try {
a = 8;
return a;
}catch (Exception e){
a = 7;
return a;
}finally {
a = 6;
}
}
结果:8 。无异常,执行finally,但返回的是 b=a=8,b指代插入临时变量表slot的位置
public int test(){
int a = 9;
try {
a = 8;
int b = 1/0;
return a;
}catch (Exception e){
a = 7;
return a;
}finally {
a = 6;
}
}
结果:7。产生异常,进入catch,执行finally,但返回的是 b=a=7,b指代插入临时变量表slot的位置
public int test(){
int a = 9;
try {
a = 8;
return a;
}catch (Exception e){
a = 7;
return a;
}finally {
a = 6;
return a;
}
}
结果:6。finally含return,返回a
总结:
try { return A }catch{ }finally{ }
原引用为A,会”备份“A,记为B (A,B都在栈上) 当A是基本类型时,不管你如何对A进行操作,返回的是B的值。 当A是引用类型。你备份的B和A指向的是堆中同一块内存,你用A任意引用操作对象,返回的都是更改后的同一个对象。
-
try无异常,执行try与finally内容,try中return返回相应值或引用的复制,也就是说,finally中只要不是对返回引用指向的对象进行更改,finally中的操作不会影响try中的返回;但如果finally中也包含return,则直接返回finally中对应的值,没有类似的复制操作,try中return无效。
-
try出现待捕获的异常,则执行catch与finally,如果catch也出现异常,则执行finally,并抛出catch中的异常,catch与finally中return操作同try。
-
try出现其他未捕获的异常,执行finally,并抛出异常
-
如果finally本身出现异常,则finally语句块停止运行,方法异常退出,并把异常抛给此方法的调用者
-
如果程序中包含
System.exit()
运行到此处则直接中断结束。