问:finally语句必定会执行吗?
答:java
若是没有执行相应的try语句则不会执行。segmentfault
在try语句中若是调用System.exit(0)方法则不会执行。布局
问:finally会在何时执行?
答:若是在try/catch语句中调用转移指令例如:return,break,continue,throw等。则会在转移指令前执行。code
若是在finally中含有return语句,那么try/catch语句的return还有做用吗?对象
先看一段代码:blog
/** * Created by gavin on 15-9-2. */ public class FinallyTest { public static void main(String[] args){ System.out.println(test1()); //3 System.out.println(test2()); //3 System.out.println(test3()); //2 System.out.println(test4()); //2 } public static int test1() { int i = 1; try { i = 2; return i; }finally { i++; return i; } } public static int test2() { int i = 1; try { i = 2; return i; }finally { i = 3; return i; } } public static int test3() { int i = 1; try { i = 2; return i; }finally { i++; } } public static int test4() { int i = 1; try { i = 2; return i; }finally { i = 3; } } }
若是你对java内存布局不是很清楚,请看这篇文章:java虚拟机类加载机制和字节码执行引擎内存
重点关注运行时栈帧结构(局部变量表槽
,操做数栈
)。get
上边的代码很是简单,来看一下字节码指令吧虚拟机
public static int test1(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=0 0: iconst_1 //定义一个常量1入栈到操做数栈 //栈1 0: 1: 1: istore_0 //出栈,存储到局部便量表槽0 //栈 0:1 1: 2: iconst_2 //定义一个常量2入栈到操做数栈 //栈2 0:1 1: 3: istore_0 //出栈,存储到局部变量表槽0 //栈 0:2 1: 4: iload_0 //从局部便量表槽0入栈到操做数栈 //栈2 0:2 1: 5: istore_1 //出栈,存储到局部变量表槽1 //栈 0:2 1:2 6: iinc 0, 1 //局部变量表槽0变量加1 //栈 0:3 1:2 9: iload_0 //从局部变量表槽0入栈到操做数栈 //栈3 0:3 1:2 10: ireturn //结束,返回 //栈3 0:3 1:2 11: astore_2 12: iinc 0, 1 15: iload_0 16: ireturn public static int test2(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=0 0: iconst_1 //定义一个常量1入栈到操做数栈 //栈1 0: 1: 1: istore_0 //出栈,存储到局部便量表槽0 //栈 0:1 1: 2: iconst_2 //定义一个常量2入栈到操做数栈 //栈2 0:1 1: 3: istore_0 //出栈,存储到局部变量表槽0 //栈 0:2 1: 4: iload_0 //从局部变量表槽0入栈 //栈2 0:2 1: 5: istore_1 //出栈,存储到局部变量表槽1 //栈 0:2 1:2 6: iconst_3 //定义一个常量3入栈 //栈3 0:2 1:2 7: istore_0 //出栈,存储到局部便量表槽0 //栈 0:3 1:2 8: iload_0 //从局部变量表槽0入栈 //栈3 0:3 1:2 9: ireturn //结束,返回 //栈3 0:3 1:2 10: astore_2 11: iconst_3 12: istore_0 13: iload_0 14: ireturn public static int test3(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=0 0: iconst_1 //定义一个常量1入栈到操做数栈 //栈1 0: 1: 1: istore_0 //出栈,存储到局部便量表槽0 //栈 0:1 1: 2: iconst_2 //定义一个常量2入栈到操做数栈 //栈2 0:1 1: 3: istore_0 //出栈,存储到局部变量表槽0 //栈 0:2 1: 4: iload_0 //从局部变量表槽0入栈 //栈2 0:2 1: 5: istore_1 //出栈,存储到局部变量表槽1 //栈 0:2 1:2 6: iinc 0, 1 //局部变量表槽0变量加一 //栈 0:3 1:2 9: iload_1 //从局部变量表槽1入栈 //栈2 0:3 1:2 10: ireturn //结束,返回 //栈2 0:3 1:2 11: astore_2 12: iinc 0, 1 15: aload_2 16: athrow public static int test4(); flags: ACC_PUBLIC, ACC_STATIC Code: stack=1, locals=3, args_size=0 0: iconst_1 //定义一个常量1入栈到操做数栈 //栈1 0: 1: 1: istore_0 //出栈,存储到局部便量表槽0 //栈 0:1 1: 2: iconst_2 //定义一个常量2入栈到操做数栈 //栈2 0:1 1: 3: istore_0 //出栈,存储到局部变量表槽0 //栈 0:2 1: 4: iload_0 //从局部变量表槽0入栈 //栈2 0:2 1: 5: istore_1 //出栈,存储到局部变量表槽1 //栈 0:2 1:2 6: iconst_3 //定义一个常量3入栈到操做数栈 //栈3 0:2 1:2 7: istore_0 //出栈,存储到局部变量表槽0 //栈 0:3 1:2 8: iload_1 //从局部变量表槽1入栈 //栈2 0:3 1:2 9: ireturn //结束,返回 //栈2 0:3 1:2 10: astore_2 11: iconst_3 12: istore_0 13: aload_2 14: athrow
咱们看到:it
在finally中没有return时,栈中最后存储的数据是try/catch中操做后数据。即finally操做后的数据存储到其余槽中,然后再加载try/catch操做后的数据。
而在finally中含有return时,栈中最后存储的数据是finally中操做后的数据。即finally操做后的数据存储到其余槽中,然后加载的是其余槽(finally)中的数据。
也就是说:若是finally中不含有return语句,finally对try/catch操做的八大基础类型不会再加载到操做数栈中。
若是返回值是对象引用,finally中的return还有待考据。