java中finally和return_finally与return之间的关系

定论

问:finally语句一定会执行吗?

答:

如果没有执行相应的try语句则不会执行。

在try语句中如果调用System.exit(0)方法则不会执行。

问:finally会在什么时候执行?

答:如果在try/catch语句中调用转移指令例如:return,break,continue,throw等。则会在转移指令前执行。

总结

finally与return之间的关系

如果在finally中含有return语句,那么try/catch语句的return还有作用吗?

先看一段代码:

/**

* 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虚拟机类加载机制和字节码执行引擎

重点关注运行时栈帧结构(局部变量表槽,操作数栈)。

上边的代码非常简单,来看一下字节码指令吧

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

我们看到:

在finally中没有return时,栈中最后存储的数据是try/catch中操作后数据。即finally操作后的数据存储到其他槽中,而后再加载try/catch操作后的数据。

而在finally中含有return时,栈中最后存储的数据是finally中操作后的数据。即finally操作后的数据存储到其他槽中,而后加载的是其他槽(finally)中的数据。

也就是说:如果finally中不含有return语句,finally对try/catch操作的八大基础类型不会再加载到操作数栈中。

如果返回值是对象引用,finally中的return还有待考据。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值