六个例子彻底理解finally语句块
来源:互联网 发布:高铁 刘志军 知乎 编辑:程序博客网 时间:2024/06/01 18:45
六个例子彻底理解finally
语句块
这篇博客主要弄清楚两个问题
1. finally
块中的代码是否一定会执行
2. finally
块中的代码什么时候被执行
首先开始第一个:
finally
块中的代码一定会被执行么?
答案是否定的,主要有以下几种情况:
1.try之前发生异常或者直接结束的情况.
finally
是与try
, catch
配套使用的,finally
生效的最大的前提就是得能进行到try语句内,例如以下这种情况就属于没有进入到try
然后finally
不执行的情况:
int i = 5 / 0; try { System.out.println("Try block"); } catch (Exception e) { System.out.println("Catch block"); }finally { System.out.println("Finally block"); }
2.try
语句内强制退出程序
比较好理解,如下:
try { System.out.println("Try block"); System.exit(0); } catch (Exception e) { System.out.println("Catch block"); }finally { System.out.println("Finally block"); } //输出 Try block
finally
是什么时候执行的?
先看实例:以下程序的输出结果是什么?
public static int test() { try { return 1; } catch (Exception e) { return 0; } finally { System.out.println("Finally block"); } } public static void main(String[] args) { System.out.println(FinallyTest.test()); }
结果:
Finally block1
为何会出现这种情况?
Java
语言的异常处理中,finally
的作用就是为了保证无论出现什么情况,finally
里面的代码一定会执行(当然并不能满足所有的情况).
由于程序执行return
就意味着结束对当前函数的调用并且跳出这个函数,因此所有的必须要执行的语句都应该在return
之前执行(除非遇到exit
函数).因此finally块中的函数也是要在return之前执行的.
如下图:
至于进行的什么处理下文再说
再看一个实例:
public static int test() { try { return 1; } catch (Exception e) { return 0; } finally { System.out.println("Finally block"); return 3; } } public static void main(String[] args) { System.out.println(FinallyTest.test()); }
结果:
Finally block3
这个实例说明如果finally
块内也包含return
语句,那么finally
内的return
语句会覆盖try-catch
内的return
结果
再来一个例子:
public static int test() { int result = 0; try { result = 1; return result; } catch (Exception e) { result = 2; return result; } finally { result = 3; System.out.println("Finally block"); } } public static void main(String[] args) { System.out.println(FinallyTest.test()); }
结果:
Finally block1
先不急于解释这种现象,再看一个类似的例子
public static StringBuilder test() { StringBuilder builder = new StringBuilder("hello"); try { return builder; } catch (Exception e) { return null; } finally { builder.append("world"); System.out.println("Finally block"); } } public static void main(String[] args) { System.out.println(FinallyTest.test()); }
结果:
Finally blockhello world
对比前面两个例子是不是更加疑惑了,但其实原因特别简单:
一个方法内部定义的变量都是存储在栈中的,当这个函数结束后,其对应的栈就会被系统回收,此时其方法内部定义的变量将不存在了,因此return
在返回的时候不是直接返回方法中的变量的值,而是复制一份,然后返回.
因此,对于前一个例子当中,由于是基本类型的数据,所有复制的是变量的数值,并且这个复制过程是在执行finally
之前的,所有finally
内修改基本类型的值没能生效,因为要输出的值早已经确定了
而后一个例子中是引用类型,复制的时候只是复制的对象的地址,finally
对变量进行修改的时候改变了对应的对象的属性,输出的时候按照地址获取属性,获取的是修改后的属性,所以是有影响的.
#现在知道前面的处理是啥了.如图:
是不是已将明了了一些了,那么再来看一个例子:
public static String test() { StringBuilder builder = new StringBuilder("hello"); try { return builder.toString(); } catch (Exception e) { return null; } finally { builder.append(" world"); System.out.println("Finally block"); } } public static void main(String[] args) { System.out.println(FinallyTest.test()); }
输出结果
Finally blockhello
细心的同学应该不会被坑到,finally
内的修改没有生效,原因在于复制的时候不是复制的StringBuilder
的地址,而是一个字符串的地址,当然也有同学会说String也是引用类型,finally
内的代码修改了对应地址的数据,但是要注意String
是一个不可变类,builder
调用的append
方法并没有对"hello"
进行任何修改,之前String
的地址对应的值是不会变化的.所以finally
内的修改没有生效.有的同学有疑惑,关于String
, StringBuilder
等对象的区别请参考这篇博客:Character , String , StringBuffer , StringBuilder , StringTokenizer 的区别.
为了对比那再看一个例子:
static class TestEntity { String mString; StringBuilder mBuilder; public TestEntity(String string, StringBuilder builder) { mString = string; mBuilder = builder; } public StringBuilder getBuilder() { return mBuilder; } } public static StringBuilder test() { TestEntity entity = new TestEntity("hello", new StringBuilder("world")); try { return entity.getBuilder(); } catch (Exception e) { return null; } finally { entity.getBuilder().append(" world"); System.out.println("Finally block"); } } public static void main(String[] args) { System.out.println(FinallyTest.test()); }
应该已经猜到结果了
Finally blockworld world
原因上面都提到了,StringBuilder
是引用类型并且是可变的,所以finally
内的修改会生效.
结束~
有不足的地方欢迎指出,另外建了个新手交流Android
开发的QQ群,欢迎加入.
群号:375276053
6 2
- 六个例子彻底理解finally语句块
- 六个例子彻底理解finally语句块
- 关于finally语句块
- Finally语句块的执行
- try{}catch(){}finally语句块
- finally语句块的作用
- try...catch...finally语句块
- try...catch...finally语句块
- java中finally语句块注意事项
- 深度辨析 Java 中的 finally 语句块
- try-catch-finally块中的退出语句
- 深度探究Java 中 finally 语句块
- finally 语句块的深度辨析
- JAVA初窥:try、catch、finally语句块中的return语句
- return之后finally块还会不会执行(try-catch块中finally的小例子)
- finally块
- finally块
- finally块
- Java泛型的实现:“禁止”泛型数组
- java算法——求最大公约数和最小公倍数
- POJ 1306 Combinations 递推 || 暴力
- 在linux下使用curl访问 多参数url GET参数问题
- Java集合简单案例
- 六个例子彻底理解finally语句块
- 阻塞队列简介
- 1分钟教你学会用adb进行无线调试
- hdu5763 Another Meaning(DP+KMP)
- Section1:UEFI概述
- 设A是n*n的对称矩阵,将A的对角线及对角线上方的元素以列为主的次序存放在一维数组B[1..n(n+1)/2]中,对上述任一元素aij(1<=i,j<=n,且i<=j)在B中的位置为()
- 复制文件夹下的内容到另一个文件夹下
- JS插件收藏
- poj 1952 BUY LOW, BUY LOWER【解法一】