【JAVA 基础】finally 执行顺序
【JAVA 基础】finally 执行顺序
public class Test {
public int getX() {
int x;
try {
x = 7;
return x;
} catch (Exception e) {
x = 8;
return x;
} finally {
x = 9;
// 接下来看注释与不注释的区别
return x;
}
}
}
写 java 的也许得到正确的结果不难,但我们的目标是知道为什么会这样?
我的疑问点其实就是在 finally 如果不加上 return 那一行,为什么返回 7,通过调试我们可以看到执行顺序是赋值 7,然后复制 9,然后返回。为什么最后变为了 7。
我们其实可以通过查看字节码文件得到问题的原因
字节码
有 return#
无 return#
tips:
- 异常也是一个变量
- finally 在无异常的情况会在执行完 try 里面代码块以后执行,但是返回值
链接
https://blog.csdn.net/u012070360/article/details/81624854
JVM 指令集整理
看字节码从这里开始。
指令码 | 助记符 | 说明 |
---|---|---|
0×00 | nop | 什么都不做 |
0×01 | aconst_null | 将 null 推送至栈顶 |
0×02 | iconst_m1 | 将 int 型 - 1 推送至栈顶 |
0×03 | iconst_0 | 将 int 型 0 推送至栈顶 |
0×04 | iconst_1 | 将 int 型 1 推送至栈顶 |
0×05 | iconst_2 | 将 int 型 2 推送至栈顶 |
0×06 | iconst_3 | 将 int 型 3 推送至栈顶 |
0×07 | iconst_4 | 将 int 型 4 推送至栈顶 |
0×08 | iconst_5 | 将 int 型 5 推送至栈顶 |
0×09 | lconst_0 | 将 long 型 0 推送至栈顶 |
0x0a | lconst_1 | 将 long 型 1 推送至栈顶 |
0x0b | fconst_0 | 将 float 型 0 推送至栈顶 |
0x0c | fconst_1 | 将 float 型 1 推送至栈顶 |
0x0d | fconst_2 | 将 float 型 2 推送至栈顶 |
0x0e | dconst_0 | 将 double 型 0 推送至栈顶 |
0x0f | dconst_1 | 将 double 型 1 推送至栈顶 |
0×10 | bipush | 将单字节的常量值 (-128~127) 推送至栈顶 |
0×11 | sipush | 将一个短整型常量值 (-32768~32767) 推送至栈顶 |
0×12 | ldc | 将 int, float 或 String 型常量值从常量池中推送至栈顶 |
0×13 | ldc_w | 将 int, float 或 String 型常量值从常量池中推送至栈顶(宽索引) |
0×14 | ldc2_w | 将 long 或 double 型常量值从常量池中推送至栈顶(宽索引) |
0×15 | iload | 将指定的 int 型本地变量推送至栈顶 |
0×16 | lload | 将指定的 long 型本地变量推送至栈顶 |
0×17 | fload | 将指定的 float 型本地变量推送至栈顶 |
0×18 | dload | 将指定的 double 型本地变量推送至栈顶 |
0×19 | aload | 将指定的引用类型本地变量推送至栈顶 |
0x1a | iload_0 | 将第 0 个 int 型本地变量推送至栈顶 |
0x1b | iload_1 | 将第 1 个 int 型本地变量推送至栈顶 |
0x1c | iload_2 | 将第 2 个 int 型本地变量推送至栈顶 |
0x1d | iload_3 | 将第 3 个 int 型本地变量推送至栈顶 |
0x1e | lload_0 | 将第 0 个 long 型本地变量推送至栈顶 |
0x1f | lload_1 | 将第 1 个 long 型本地变量推送至栈顶 |
0×20 | lload_2 | 将第 2 个 long 型本地变量推送至栈顶 |
0×21 | lload_3 | 将第 3 个 long 型本地变量推送至栈顶 |
0×22 | fload_0 | 将第 0 个 float 型本地变量推送至栈顶 |
0×23 | fload_1 | 将第 1 个 float 型本地变量推送至栈顶 |
0×24 | fload_2 | 将第 2 个 float 型本地变量推送至栈顶 |
0×25 | fload_3 | 将第 3 个 float 型本地变量推送至栈顶 |
0×26 | dload_0 | 将第 0 个 double 型本地变量推送至栈顶 |
0×27 | dload_1 | 将第 1 个 double 型本地变量推送至栈顶 |
0×28 | dload_2 | 将第 2 个 double 型本地变量推送至栈顶 |
0×29 | dload_3 | 将第 3 个 double 型本地变量推送至栈顶 |
0x2a | aload_0 | 将第 0 个引用类型本地变量推送至栈顶 |
0x2b | aload_1 | 将第 1 个引用类型本地变量推送至栈顶 |
0x2c | aload_2 | 将第 2 个引用类型本地变量推送至栈顶 |
0x2d | aload_3 | 将第 3 个引用类型本地变量推送至栈顶 |
0x2e | iaload | 将 int 型数组指定索引的值推送至栈顶 |
0x2f | laload | 将 long 型数组指定索引的值推送至栈顶 |
0×30 | faload | 将 float 型数组指定索引的值推送至栈顶 |
0×31 | daload | 将 double 型数组指定索引的值推送至栈顶 |
0×32 | aaload | 将引用型数组指定索引的值推送至栈顶 |
0×33 | baload | 将 boolean 或 byte 型数组指定索引的值推送至栈顶 |
0×34 | caload | 将 char 型数组指定索引的值推送至栈顶 |
0×35 | saload | 将 short 型数组指定索引的值推送至栈顶 |
0×36 | istore | 将栈顶 int 型数值存入指定本地变量 |
0×37 | lstore | 将栈顶 long 型数值存入指定本地变量 |
0×38 | fstore | 将栈顶 float 型数值存入指定本地变量 |
0×39 | dstore | 将栈顶 double 型数值存入指定本地变量 |
0x3a | astore | 将栈顶引用型数值存入指定本地变量 |
0x3b | istore_0 | 将栈顶 int 型数值存入第 0 个本地变量 |
0x3c | istore_1 | 将栈顶 int 型数值存入第 1 个本地变量 |
0x3d | istore_2 | 将栈顶 int 型数值存入第 2 个本地变量 |
0x3e | istore_3 | 将栈顶 int 型数值存入第 3 个本地变量 |
0x3f | lstore_0 | 将栈顶 long 型数值存入第 0 个本地变量 |
0×40 | lstore_1 | 将栈顶 long 型数值存入第 1 个本地变量 |
摘抄自网络,便于检索查找。