网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过试验,至少有两种情况下finally语句时不会被执行的

  (1)try语句没有被执行到,如在try语句之前就返回了,这样finally语句就不会执行,这也说明了finally语句被执行的必要而非充分条件是:相应的try语句一定被执行到。

  (2)在try块中有System.exit(0);这样的语句,System.exit(0);是终止Java虚拟机JVM的,连JVM都停止了,所有都结束了,当然finally语句也不会被执行到。

  当然还有很多人探讨Finally语句的执行与return的关系,颇为让人迷惑,不知道finally语句是在try的return之前执行还是之后执行?我也是一头雾水,我觉得他们的说法都不正确,我觉得应该是:finally语句是在try的return语句执行之后,return返回之前执行。这样的说法有点矛盾,也许是我表述不太清楚,下面我给出自己试验的一些结果和示例进行佐证,有什么问题欢迎大家提出来。

1、finally语句在return语句执行之后return返回之前执行的。

 1 package com.meng.javalanguage.finallytest;
 2
 3 public class FinallyTest1 {
 4
 5     public static void main(String[] agrs) {
 6         System.out.println(test1());
 7     }
 8
 9     public static int test1() {
10         int b = 20;
11         try {
12             System.out.println("try block");
13
14             return b += 80;
15         }catch(Exception e) {
16             System.out.println("catch block");
17         }
18         finally {
19             System.out.println("finally block");
20
21             if(b > 25) {
22                 System.out.println("b > 25,b = " + b);
23             }
24         }
25         return b;
26     }
27 }

运行结果是:

  说明return语句已经执行了再去执行finally语句,不过并没有直接返回,而是等finally语句执行完了再返回结果。

  如果觉得这个例子不足以说明这个情况的话,下面再加个例子加强证明结论:

 1 package com.meng.javalanguage.finallytest;
 2
 3 public class FinallyTest1 {
 4
 5     public static void main(String[] args) {
 6         System.out.println(test11());
 7     }
 8
 9     public static String test11() {
10         try {
11             System.out.println("try block");
12
13             return test12();
14         } finally {
15             System.out.println("finally block");
16         }
17     }
18
19     public static String test12() {
20         System.out.println("return statement");
21
22         return "after return";
23     }
24 }

运行结果为:

  说明try中的return语句先执行了但并没有立即返回,等到finally执行结束后再返回。

  这里大家可能会想:如果finally里也有return语句,那么是不是就直接返回了,try中的return就不能返回了?看下面。

2、finally块中的return语句会覆盖try块中的return返回。

 1 package com.meng.javalanguage.finallytest;
 2
 3 public class FinallyTest2 {
 4
 5     public static void main(String[] args) {
 6         System.out.println(test2());
 7     }
 8
 9     @SuppressWarnings("finally")
10     public static int test2() {
11         int b = 20;
12
13         try {
14             System.out.println("try block");
15
16             return b += 80;
17         }catch(Exception e) {
18
19             System.out.println("catch block");
20         }
21         finally {
22             System.out.println("finally block");
23
24             if(b > 25) {
25                 System.out.println("b > 25, b = " + b);
26             }
27
28             return 200;
29         }
30
31 //        return b;
32     }
33 }

运行结果是:

  这说明finally里的return直接返回了,就不管try中是否还有没有返回语句。这里还有个小细节需要注意,finally里加上return过后,finally外面的return b;就变成了不可到达的语句,也就是永远不能被执行到,所以需要注释掉否则编译器报错

  这里大家可能又想:如果finally里没有return语句,但修改了b的值,那么try中return返回的是修改后的值还是原值?看下面。

3、如果finally语句中没有return语句覆盖返回值,那么原来的返回值可能因为finally里的修改而改变也可能不变。

测试用例1:

 1 package com.meng.javalanguage.finallytest;
 2
 3 public class FinallyTest3 {
 4
 5     public static void main(String[] args) {
 6         System.out.println(test3());
 7     }
 8
 9     public static int test3() {
10         int b = 20;
11
12         try {
13             System.out.println("try block");
14
15             return b += 80;
16         }catch(Exception e) {
17
18             System.out.println("catch block");
19         }
20         finally {
21
22             System.out.println("finally block");
23
24             if(b > 25) {
25                 System.out.println("b > 25, b = " + b);
26             }
27
28             b = 150;
29         }
30
31         return 2000;
32     }
33 }

运行结果是:

测试用例2:

 1 package com.meng.javalanguage.finallytest;
 2
 3 import java.util.HashMap;
 4 import java.util.Map;
 5
 6 public class FinallyTest6 {
 7     public static void main(String[] args) {
 8         System.out.println(getMap().get("KEY").toString());
 9     }
10
11     public static Map<String, String> getMap() {
12         Map<String, String> map = new HashMap<String, String>();
13
14         map.put("KEY","INIT");
15
16         try {
17             map.put("KEY", "TRY");
18             return map;
19         }catch(Exception e) {
20             map.put("KEY", "CATCH");
21         }
22         finally {
23             map.put("KEY", "FINALLY");
24             map = null;
25         }
26
27         return map;
28     }
29 }

运行结果是:

  为什么测试用例1中finally里的b = 150;并没有起到作用而测试用例2中finally的map.put("KEY","FINALLY");起了作用而map = null;却没起作用呢?这就是Java到底是传值还是传址的问题了,return语句已经执行了:

  1)再对b操作(b = 150;)相当于参数传递,操作的b是形式参数,不影响实际参数的值;

  2)对map的操作(map = null)与1)同理,同样不影响实际参数的值;

  3)对于map.put("KEY","FINALLY"),形参和实参的内容一致,且因为map为引用类型,所以形参和实参存储的为地址。此时调用形参改变自身内容的方法将会影响到该地址指向的对象的内容。所以,map中"KEY"对应的值改变了

  测试用例1还可以说明:返回语句是try中的return语句而不是finally外面的return 2000;这句。

4、try块里的return语句在异常的情况下不会被执行,这样具体返回哪个看情况。

 1 package com.meng.javalanguage.finallytest;
 2
 3 public class FinallyTest4 {
 4     public static void main(String[] args) {
 5         System.out.println(test4());
 6     }
 7
 8     public static int test4() {
 9         int b = 20;
10
11         try {
12             System.out.println("try block");
13
14             b = b / 0;
15
16             return b += 80;
17         } catch(Exception e) {
18
19             b += 15;
20             System.out.println("catch block");
21         }
22         finally {
23
24             System.out.println("finally block");
25
26             if(b > 25) {
27                 System.out.println("b > 25,b = " + b);
28             }
29
30             b += 50;
31
32         }
33         return b;
34
35
36     }
37
38 }

运行结果是:

  这里因为在return之前发生了除0异常,所以try中的return不会被执行到,而是接着执行捕获异常的catch语句和最终的finally语句,此时两者对b的修改都影响了最终的返回值,这时return b;就返回了最后对b进行修改后的值。当然如果你这里将return b改为return 300什么的,最后返回的就是300,这毋容置疑。

  这里大家可能又有疑问:如果catch中有return语句呢?当然只有在异常的情况下才有可能会执行,那么是在finally之前就返回吗?看下面

5、当发生异常后,catch中的return执行情况与未发生异常时try中return的执行情况完全一样。

 1 package com.meng.javalanguage.finallytest;
 2
 3 public class FinallyTest5 {
 4
 5     public static void main(String[] args) {
 6         System.out.println(test5());
 7     }
 8
 9     public static int test5() {
10         int b = 20;
11
12         try {
13             System.out.println("try block");
14
15             b = b / 0;
16
17             return b += 80;
18         }catch(Exception e) {
19             System.out.println("catch block");
20
21             return b += 15;
22         }
23         finally {
24
25             System.out.println("finally block");
26
27             if(b > 25) {
28                 System.out.println("b > 25,b = " + b);
29             }
30
31             b += 50;
32         }
33
34 //        return b;
35     }
36 }

运行结果是:

  说明了发生异常后,catch中的return语句先执行,确定了返回值后再去执行finally块,执行完了catch再返回,finally里对b的改变对返回值无影响,原因同前面 一样,也就是说情况与try中的return语句执行完全一样。

  最后总结:finally块的语句在try或catch中的return语句执行之后返回之前执行,且finally里的修改语句可能影响也可能不影响try或catch块中return已经确定的返回值,若finally里也有return语句则覆盖try或catch中的return语句直接返回

  转载自《Java finally语句到底是在return之前还是之后执行?》

【转】Java finally语句到底是在return之前还是之后执行?相关推荐

  1. Java finally语句到底是在return之前还是之后执行?

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finall ...

  2. java finally在return_Java finally语句到底是在return之前还是之后执行?

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 网上有很多人探讨Java中异常捕获机制try...catch...finally块中的finall ...

  3. java的tey语句return了_Java finally语句到底是在return之前还是之后执行?

    网上有很多人探讨Java中异常捕获机制try-catch-finally块中的finally语句是不是一定会被执行?很多人都说不是,当然他们的回答是正确的,经过我试验,至少有两种情况下finally语 ...

  4. java 删除语句_是java语句

    <21天学通Java(第7版)>-- 第2章 Java编程基础 2.1 语句和表达式 本节书摘来异步社区<21天学通Java(第7版)>一书中的第2章,第2.1节,作者: [美 ...

  5. java webservice报文过长_工作1-5年的Java程序猿到底需要怎样的一个技术栈?

    工作1-5年的Java程序猿到底需要怎样的一个技术栈? 前言: 具有1-5年开发经验的程序员 需要学习的内容其实还有很多很多. 今天跟大家交流一下希望分享出来的对大家能够有帮助,这是我这些年总结出的一 ...

  6. java switch语句_Java 14:查看更新的switch语句

    java switch语句 于2020年3月发布的JDK 14带有switch语句的更新版本. 这是JDK 12和JDK 13中的预览功能. 要了解差异,让我们看一个简单的示例. 假设我们要基于Day ...

  7. 云漫圈 | finally到底是在return之前执行还是return之后执行?

    戳蓝字"CSDN云计算"关注我们哦! 文章来自:程序员乔戈里作者:乔戈里qgl --下课后-- public class Main { public static void mai ...

  8. Java基础结构语句和IDEA使用和数组

    Java基础结构语句和IDEA和数组 基本类型和引用类型 static 第一章:结构语句 1.1.1三元运算符 1.1.2switch语句 1.1.3do-while循环 第二章:IDEA 2.1_I ...

  9. Java for 语句简化写法_Java 8 Lambda 写法与简化

    Java 8 的 Lambda 表达式的实现方式还是基于已有的字节码指令,由 Lambda 表达式的方法签名结合上下文并经由 SAM 推断出正确的类型来.Java 8 的 Lambda 完整书写格式是 ...

最新文章

  1. 力扣(LeetCode)刷题,简单题(第5期)
  2. 组合数函数-快速提取所有可能的组合数
  3. cryptojs aes加密每次结果不同_Javascript加密算法标准库,支持Nodejs+浏览器——crypto-js...
  4. 画出HTML DOM对象层次图。文档对象document有哪些常用的属性和方法?
  5. ORM多表查询——关联查询
  6. AndroidTv Home界面实现原理(二)——Leanback 库的主页卡位缩放动画源码解析
  7. SAP Cloud Platform approuter的本地安装
  8. vue中设置height:100%无效的问题及解决方法
  9. LXD 2.0 系列(十二):调试,及给 LXD 做贡献
  10. Java LocalDate类| 带示例的getEra()方法
  11. 敏捷开发团队管理系列之五:大型研发团队的切分(刚参加3.17 MDP团队管理场次的读者请看)...
  12. Mycat分布式数据库架构解决方案--搭建MySQL读写分离环境--一主多从
  13. 架构设计 —— 性能选型、高可用
  14. linux服务器数据备份到本地硬盘_如何备份硬盘数据,最简单的方法是什么?
  15. 【hdu1506/牛客小A的柱形图】单调栈入门题目
  16. 如何解决Alreader不自动滚动
  17. 【入门】用matlab做数字信号处理(学习记录)
  18. CrazyBox常见问题
  19. 我的世界Java版最诡异的种子_我的世界:比666还诡异的故障种子,无限复制结构?官方:还是特性...
  20. Ecshop会员注册的Email 电子邮箱改成非必填项

热门文章

  1. 如何用staruml画包图_StarUML的9种图
  2. 转正答辩ppt_同心同行 乘风破浪 兴业装饰新员工转正考核圆满完成
  3. MySQL表的key怎么设置为yes_MySQL 修改账号密码方法
  4. mysql怎么防止误操作_MySQL数据库防止人为误操作的实例讲解
  5. 虚拟机vcenter如何增加磁盘_vSphere 6 下创建数据库RAC虚拟机共享磁盘
  6. 零基础学python语言_零基础如何入门Python语言?有哪些学习建议?
  7. 公司--页面调用日期控件 WdatePicker日历控件使用方法
  8. ztree 默认选中节点_用户管理、角色管理、模块管理、zTree的使用
  9. 能写出HTML语言框架结构,HTML语言—框架最新.ppt
  10. python默认数据类型转换_Python 数据类型转换