大家好,我是考100分的小小码 ,祝大家学习进步,加薪顺利呀。今天说一说try catch finally语句_try catch后面的语句还会执行吗,希望您对编程的造诣更进一步.
try-catch-finally 语句是在各种情况下是如何执行的?
查看jvm编译后的字节码,可以清晰的解释这个问题。
官方规范参考:《The Java® Virtual Machine Specification Java SE 8 Edition》 3.13 Compiling finally
该文档给出的示例是基于50.0及之前版本的例子,仅供辅助理解。但是文档中总结了try-catch-finally 流程执行的四种情况:
- 语句块内的所有语句正常执行结束
- 通过 return 语句退出方法
- 执行 break continue 语句
- (try block)抛出异常
下面给出java8版本的实践demo,对照编译后的字节码可解释。
java代码:
/**
* 右键文件 -> externalTools -> javap
*/
public class TestForFinally {
private int tryBlock;
private int catchBlock;
private int finallyBlock;
private int methodExit;
/**
* 语句块内的所有语句正常执行结束
*/
public void test1() {
try {
tryBlock = 0;
} catch (Exception e) {
catchBlock = 1;
} finally {
finallyBlock = 2;
}
methodExit = 3;
}
/**
* 通过 return 语句退出方法
*/
public void test2(){
try {
tryBlock = 0;
return;
} catch (Exception e) {
catchBlock = 1;
} finally {
finallyBlock = 2;
}
methodExit = 3;
}
/**
* 执行 break continue 语句
*/
public void test3(){
for (int i = 0; i < 100; i++) {
try {
tryBlock = 0;
} catch (Exception e) {
catchBlock = 1;
break;
} finally {
finallyBlock = 2;
}
}
methodExit = 3;
}
/**
* (try block)抛出异常
*/
public void test4(){
try {
tryBlock = 0;
throw new RuntimeException("throw from try block");
} catch (Exception e) {
catchBlock = 1;
} finally {
finallyBlock = 2;
}
methodExit = 3;
}
}
字节码:
public individual.jmy.bytecode.TestForFinally();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public void test1();
Code:
0: aload_0
1: iconst_0
2: putfield #2 // Field tryBlock:I
5: aload_0
6: iconst_2
7: putfield #3 // Field finallyBlock:I
10: goto 35
13: astore_1
14: aload_0
15: iconst_1
16: putfield #5 // Field catchBlock:I
19: aload_0
20: iconst_2
21: putfield #3 // Field finallyBlock:I
24: goto 35
27: astore_2
28: aload_0
29: iconst_2
30: putfield #3 // Field finallyBlock:I
33: aload_2
34: athrow
35: aload_0
36: iconst_3
37: putfield #6 // Field methodExit:I
40: return
Exception table:
from to target type
0 5 13 Class java/lang/Exception
0 5 27 any
13 19 27 any
public void test2();
Code:
0: aload_0
1: iconst_0
2: putfield #2 // Field tryBlock:I
5: aload_0
6: iconst_2
7: putfield #3 // Field finallyBlock:I
10: return
11: astore_1
12: aload_0
13: iconst_1
14: putfield #5 // Field catchBlock:I
17: aload_0
18: iconst_2
19: putfield #3 // Field finallyBlock:I
22: goto 33
25: astore_2
26: aload_0
27: iconst_2
28: putfield #3 // Field finallyBlock:I
31: aload_2
32: athrow
33: aload_0
34: iconst_3
35: putfield #6 // Field methodExit:I
38: return
Exception table:
from to target type
0 5 11 Class java/lang/Exception
0 5 25 any
11 17 25 any
public void test3();
Code:
0: iconst_0
1: istore_1
2: iload_1
3: bipush 100
5: if_icmpge 49
8: aload_0
9: iconst_0
10: putfield #2 // Field tryBlock:I
13: aload_0
14: iconst_2
15: putfield #3 // Field finallyBlock:I
18: goto 43
21: astore_2
22: aload_0
23: iconst_1
24: putfield #5 // Field catchBlock:I
27: aload_0
28: iconst_2
29: putfield #3 // Field finallyBlock:I
32: goto 49
35: astore_3
36: aload_0
37: iconst_2
38: putfield #3 // Field finallyBlock:I
41: aload_3
42: athrow
43: iinc 1, 1
46: goto 2
49: aload_0
50: iconst_3
51: putfield #6 // Field methodExit:I
54: return
Exception table:
from to target type
8 13 21 Class java/lang/Exception
8 13 35 any
21 27 35 any
public void test4();
Code:
0: aload_0
1: iconst_0
2: putfield #2 // Field tryBlock:I
5: new #7 // class java/lang/RuntimeException
8: dup
9: ldc #8 // String throw from try block
11: invokespecial #9 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
14: athrow
15: astore_1
16: aload_0
17: iconst_1
18: putfield #5 // Field catchBlock:I
21: aload_0
22: iconst_2
23: putfield #3 // Field finallyBlock:I
26: goto 37
29: astore_2
30: aload_0
31: iconst_2
32: putfield #3 // Field finallyBlock:I
35: aload_2
36: athrow
37: aload_0
38: iconst_3
39: putfield #6 // Field methodExit:I
42: return
Exception table:
from to target type
0 15 15 Class java/lang/Exception
0 21 29 any
需要特别说明的是,有一种情况是catch block抛出异常,参考test1方法对应字节码的异常表,catch block 抛出异常,会跳转到
27: astore_2
该语句会将从catch block 抛出的异常存入局部变量表的index=2中。 并在最后执行:
33: aload_2
34: athrow
该语句从局部变量表中读取index=2的数(即catch block 抛出的异常),并抛出。
由此可见,catch block 如果抛出异常,则该方法向调用方抛出的是catch block产生的异常,如果try block 也产生了异常,则会被覆盖。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/13900.html