try catch finally 常见格式如下:

try{//应用代码}catch(Exception e){//异常捕捉处理}finally{//资源释放、流关闭等等
}

通常执行顺序:

  • try有异常时,try-catcy-finally
  • try无异常时,try-finally

那么如果有返回值呢?try catch finally 每个部分均有return语句呢?finally中抛出异常呢?

下面逐个实践分析。

【1】不抛异常,测试return不同地方返回

① 不抛异常,方法末尾处return

测试代码如下:

public class TestTryCatch {public static void main(String[] args){int test1 = test1();System.out.println("main block : "+test1);}public static int test1(){int i = 1;try{i++;System.out.println("try block, i = "+i);}catch(Exception e){i++;System.out.println("catch block i = "+i);}finally{i = 10;System.out.println("finally block i = "+i);}return i;}
}

测试结果如下:

try block, i = 2
finally block i = 10
main block : 10

try catch finally每个部分,基本类型变量 i 都被修改值,最后返回值取finally中i的最终值。此时整个方法中只有一个局部变量 i 。

即,方法末尾处返回的变量取值于最后一次被修改的值!


② 在try catch 部分分别放return语句

测试代码如下:

public static int test2(){int i = 1;try{i++;System.out.println("try block, i = "+i);return i;}catch(Exception e){i++;System.out.println("catch block i = "+i);return i;}finally{i = 10;System.out.println("finally block i = "+i);}}

测试结果如下:

try block, i = 2
finally block i = 10
main block : 2

注意,这里main中获取test2的返回值为 2 不是 10!

分析如下:

代码顺序执行从try到finally,由于finally是无论如何都会执行的,所以try里的语句并不会直接返回。

在try语句的return块中,return返回的引用变量并不是try语句外定义的引用变量i,而是系统重新定义了一个局部引用i’,这个引用指向了引用i对应的值,也就是2。

即使在finally语句中把引用i指向了值10,因为return返回的引用已经不是i,而是i',所以引用i的值和try语句中的返回值无关了。

查看test2编译后源码如下:

  public static int test2() {byte i = 1;int var2;try {int i;try {i = i + 1;System.out.println("try block, i = " + i);//可以看到返回的是var1int var1 = i;return var1;} catch (Exception var6) {i = i + 1;System.out.println("catch block i = " + i);var2 = i;}} finally {i = 10;System.out.println("finally block i = " + i);}return var2;}

可以看到try处返回的是var1 , 方法最后返回的是var2 ! 基本类型之间是值传递,故而在finally中对 i 进行了重新赋值,也不会影响var1 var2变量的值。

即,try中有返回值的情况时(不抛异常不走catch),finally修改变量对try返回值无影响!


那么可能会问这里 i 为基本类型 int ,如果换成其包装类 Integer呢?

代码如下:

public static int test3(){Integer i = 1;try{i++;System.out.println("try block, i = "+i);return i;}catch(Exception e){i++;System.out.println("catch block i = "+i);return i;}finally{i = 10;System.out.println("finally block i = "+i);}}

测试结果如下:

try block, i = 2
finally block i = 10
main block : 2

没有发生变化!其编译后源码如下:

public static int test3() {Integer i = Integer.valueOf(1);int var2;try {i = Integer.valueOf(i.intValue() + 1);System.out.println("try block, i = " + i);int var1 = i.intValue();return var1;} catch (Exception var7) {i = Integer.valueOf(i.intValue() + 1);System.out.println("catch block i = " + i);var2 = i.intValue();} finally {i = Integer.valueOf(10);System.out.println("finally block i = " + i);}return var2;}

我们知道基本类型有自动拆箱装箱操作,Integer自身维护了一个字节缓存数组。 Integer.valueOf()并不会每次都创建一个新的对象。

public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}

那么可能仍旧质疑,返回类型修改呢?将int 改为Integer,并且将i 赋值200>127,再次测试:

// i 为 Integerpublic static Integer test4(){Integer i = 200;try{i++;System.out.println("try block, i = "+i);return i;}catch(Exception e){i++;System.out.println("catch block i = "+i);return i;}finally{i = 210;System.out.println("finally block i = "+i);}}

测试结果如下:

try block, i = 201
finally block i = 210
main block : 201

查看其编译后源码如下:

public static Integer test4() {Integer i = Integer.valueOf(200);Integer var2;try {i = Integer.valueOf(i.intValue() + 1);System.out.println("try block, i = " + i);Integer var1 = i;return var1;} catch (Exception var7) {i = Integer.valueOf(i.intValue() + 1);System.out.println("catch block i = " + i);var2 = i;} finally {i = Integer.valueOf(210);System.out.println("finally block i = " + i);}return var2;}

仍旧是两个变量,try中return 处返回的是其局部变量 var1 , 方法结尾返回的是try外的方法局部变量 var2 ! 表明基本类型和其包装类型不会被finally中赋值语句影响。

这里有个问题,int的包装类型Integer也是对象,为什么不是引用传递而是值传递效果呢?

想想看。


如果是引用类型呢?换一个引用类型 list !

测试代码如下:

public static List<Object> test5(){List<Object> list = new ArrayList<>();try{list.add("try");System.out.println("try block");return list;}catch(Exception e){list.add("catch");System.out.println("catch block");return list;}finally{list.add("finally");System.out.println("finally block ");}}

测试结果如下:

try block
finally block
main block : [try, finally]

方法编译后的源码如下:

public static List<Object> test5() {ArrayList list = new ArrayList();ArrayList var2;try {list.add("try");System.out.println("try block");ArrayList var1 = list;return var1;} catch (Exception var6) {list.add("catch");System.out.println("catch block");var2 = list;} finally {list.add("finally");System.out.println("finally block ");}return var2;}

可以看到,finally里对list集合的操作生效了,这是为什么呢。我们知道基本类型在栈中存储,而对于非基本类型是存储在堆中的,返回的是堆中的地址,因此内容被改变了–典型的引用传递。


③ 在try catch finally都放return语句

基本类型如下:

// try catch finally处 returnpublic static int test21(){int i = 1;try{i++;System.out.println("try block, i = "+i);return i;}catch(Exception e){i++;System.out.println("catch block i = "+i);return i;}finally{i = 10;System.out.println("finally block i = "+i);return i;}}

测试结果如下:

try block, i = 2
finally block i = 10
main block : 10

方法编译后的源码如下:

public static int test21() {byte i = 1;try {int i;try {i = i + 1;System.out.println("try block, i = " + i);} catch (Exception var6) {i = i + 1;System.out.println("catch block i = " + i);}} finally {i = 10;System.out.println("finally block i = " + i);return i;}}

可以看到,是从finally语句块中返回的。可见,JVM是忽略了try中的return语句即,如果finally中有return语句,则会忽略try中return。

但IDE中会对finally中加的return有黄色警告提示,这是为什么呢,在try里加入一行会执行异常的代码,如下:

// try catch finally处 returnpublic static int test22(){int i = 1;try{i++;int m = i / 0 ;System.out.println("try block, i = "+i);return i;}catch(Exception e){i++;System.out.println("catch block i = "+i);return i;}finally{i = 10;System.out.println("finally block i = "+i);return i;}}

测试结果如下:

catch block i = 3
finally block i = 10
main block : 10

可以看到,因为finally中有return语句,try、catch中的异常被消化掉了,屏蔽了异常的发生,这与初期使用try、catch的初衷是相违背的,因此编译器也会提示警告。

通常,不建议在finally中放return语句。


引用类型如下:

public static List<Object> test51(){List<Object> list = new ArrayList<>();try{list.add("try");System.out.println("try block");return list;}catch(Exception e){list.add("catch");System.out.println("catch block");return list;}finally{list.add("finally");System.out.println("finally block ");return list;}}

测试结果如下:

try block
finally block
main block : [try, finally]

其方法编译后的源码如下:

 public static List<Object> test51() {ArrayList list = new ArrayList();try {list.add("try");System.out.println("try block");} catch (Exception var6) {list.add("catch");System.out.println("catch block");} finally {list.add("finally");System.out.println("finally block ");return list;}}

根据源码即可看到,方法最后返回的是finally中的list,list为引用类型,整个方法只有一个list。

在try中抛出一个异常,测试如下:

public static List<Object> test52(){List<Object> list = new ArrayList<>();try{list.add("try");int i = 10/0;System.out.println("try block");return list;}catch(Exception e){list.add("catch");System.out.println("catch block");return list;}finally{list.add("finally");System.out.println("finally block ");return list;}}

测试结果如下:

catch block
finally block
main block : [try, catch, finally]

方法编译后的源码如下:

public static List<Object> test52() {ArrayList list = new ArrayList();try {list.add("try");int i = 10 / 0;System.out.println("try block");} catch (Exception var6) {list.add("catch");System.out.println("catch block");} finally {list.add("finally");System.out.println("finally block ");return list;}}

总结,finally中放return语句将会忽略try catch中的return语句。方法的返回值将会由finally中return语句决定。


④ 额外测试Integer包装类型

测试代码如下:

public static Integer test42(){Integer i = new Integer(100);try{i++;System.out.println("try block, i = "+i);return i;}catch(Exception e){i++;System.out.println("catch block i = "+i);return i;}finally{i = new Integer(110);System.out.println("finally block i = "+i);}}

测试结果如下:

try block, i = 101
finally block i = 110
main block : 101

方法编译后的代码如下:

public static Integer test42() {Integer i = new Integer(100);Integer var2;try {i = Integer.valueOf(i.intValue() + 1);System.out.println("try block, i = " + i);Integer var1 = i;return var1;} catch (Exception var7) {i = Integer.valueOf(i.intValue() + 1);System.out.println("catch block i = " + i);var2 = i;} finally {i = new Integer(110);System.out.println("finally block i = " + i);}return var2;}

总结

  • try 中return,finally不return,则return返回的值根据其是基本类型or引用类型有所不同;
  • finally中有return,则会忽略try catch中的return(返回忽略)和异常(异常屏蔽)。

【2】抛出异常,测试不同地方return返回

① try中抛异常,方法末尾处返回

测试代码如下:

// 方法末尾处 return  try中抛异常public static int test11(){int i = 1;try{i++;int m = i/0;System.out.println("try block, i = "+i);}catch(Exception e){i++;System.out.println("catch block i = "+i);}finally{i = 10;System.out.println("finally block i = "+i);}return i;}

测试结果如下:

catch block i = 3
finally block i = 10
main block : 10

方法编译后源码如下:

public static int test11() {byte i = 1;try {int i;try {i = i + 1;int m = i / 0;System.out.println("try block, i = " + i);} catch (Exception var5) {i = i + 1;System.out.println("catch block i = " + i);}} finally {i = 10;System.out.println("finally block i = " + i);}return i;}

② try catch中return,try中抛异常

测试代码如下:

 // try catch return  try中抛异常public static int test12(){int i = 1;try{i++;int m = i/0;System.out.println("try block, i = "+i);return i;}catch(Exception e){i++;System.out.println("catch block i = "+i);return i;}finally{i = 10;System.out.println("finally block i = "+i);}}

测试结果如下:

catch block i = 3
finally block i = 10
main block : 3

方法编译后源码如下:

public static int test12() {byte i = 1;int var2;try {int i;try {i = i + 1;int m = i / 0;System.out.println("try block, i = " + i);var2 = i;return var2;} catch (Exception var6) {i = i + 1;System.out.println("catch block i = " + i);var2 = i;}} finally {i = 10;System.out.println("finally block i = " + i);}return var2;}

此时程序从catch的return处返回,返回值var2catch语句块中的i===3。由于变量i是基本类型,故finally中语句执行对程序返回值无影响。


③ try catch finally处return try中抛异常

参考【1.3】–忽略try、catch中的return,并屏蔽异常。

④ finally中抛出异常

测试代码如下:

 // try catch finally处 return try finally 抛出异常public static int test23(){int i = 1;try{i++;int m = i / 0 ;System.out.println("try block, i = "+i);return i;}catch(Exception e){i++;System.out.println("catch block i = "+i);return i;}finally{i = 10;int m = i / 0 ;System.out.println("finally block i = "+i);return i;}}

测试结果如下:

catch block i = 3
Exception in thread "main" java.lang.ArithmeticException: / by zeroat com.jane.TestTryCatch.test23(TestTryCatch.java:222)at com.jane.TestTryCatch.main(TestTryCatch.java:23)

方法编译后源码如下:

public static int test23() {label39: {byte i = 1;boolean var8 = false;label36: {try {int i;try {var8 = true;i = i + 1;int m = i / 0;System.out.println("try block, i = " + i);var8 = false;break label36;} catch (Exception var9) {i = i + 1;System.out.println("catch block i = " + i);var8 = false;}} finally {if(var8) {i = 10;int var5 = i / 0;System.out.println("finally block i = " + i);return i;}}}}}

这个提示表示的是finally里的异常信息,也就是说一旦finally里发生异常,try、catch里的异常信息即被消化掉了,也达不到异常信息处理的目的。


【3】总结

  • try 中是应用代码,catch是异常捕捉处理,finally通常用来进行资源释放、流关闭等。
  • 执行顺序为try-catch-finally(try中抛了异常),try-finally(try中未抛异常);
  • 只有方法末尾处返回时,返回值由try-catch-finally决定
  • 如果try、catch中有return语句,finally中没有return,那么在finally中修改引用类型、静态变量将会对try 、catch中的return值有影响,基本类型和包装类型无影响。
  • 尽量不要在finally中使用return语句,如果使用的话,会忽略try、catch中的返回语句,也会忽略try、catch中的异常,屏蔽了错误的发生。
  • finally中避免再次抛出异常,一旦finally中发生异常,代码执行将会抛出finally中的异常信息,try、catch中的异常将被忽略。

参考博文:JVM中的常量池技术

细琢磨,try catch finally 执行顺序与返回值相关推荐

  1. try catch finally return的执行顺序与返回值探究

    下午看了一下百度文库中下载下来的java笔试题,其中一道就是关于这个问题的,所以写了个测试程序验证了一下,另外具体的理论知识搜罗了网上的资料. 测试程序如下: package com.andy.cod ...

  2. Promise—关于catch(你真的了解catch的执行顺序吗)

    一.问题 今天突然被同事问到一个问题,以下代码怎么输出: Promise.all([new Promise(res => res(0)), new Promise((res, rej) => ...

  3. 关于ExecuteNonQuery执行存储过程的返回值 、、实例讲解存储过程的返回值与传出参数、、、C#获取存储过程的 Return返回值和Output输出参数值...

    关于ExecuteNonQuery执行存储过程的返回值 用到过ExecuteNonQuery()函数的朋友们在开发的时候肯定这么用过. if(cmd.ExecuteNonQuery("xxx ...

  4. C#线程池ThreadPool.QueueUserWorkItem接收线程执行的方法返回值

    最近在项目中需要用到多线程,考虑了一番,选择了ThreadPool,我的需求是要拿到线程执行方法的返回值, 但是ThreadPool.QueueUserWorkItem的回调方法默认是没有返回值的,搜 ...

  5. try catch嵌套执行顺序测试

    分享一段测试try catch 执行顺序和那些代码后续执行,那么不执行的代码: @Testpublic void testTryCatch(){try {System.out.println(&quo ...

  6. try { } catch{ } finally{ } 执行顺序总结

    publicclass TestTry { publicstaticvoid main(String[] args) { TestTry t = new TestTry(); System.out.p ...

  7. python try catch finally执行顺序_对python中的try、except、finally 执行顺序详解

    如下所示: def test1(): try: print('to do stuff') raise Exception('hehe') print('to return in try') retur ...

  8. system函数的返回值和执行脚本的返回值

    1.先统一两个说法: (1)system返回值:指调用system函数后的返回值,比如上例中status为system返回值 (2)shell返回值:指system所调用的shell命令的返回值,比如 ...

  9. python中字典不自动排序/删除指定类型文件/执行可执行文件的返回值

    1.python 字典的用法 from collections import OrderedDict dict =OrderedDict() dict['foo']=3 dcit['aol']=1 2 ...

最新文章

  1. Linux ifconfig指令
  2. [国家集训队] 特技飞行
  3. 高并发环境下,6个构建缓存服务需要注意的问题
  4. 下面介绍几种查看linux版本信息的方法和GCC版本
  5. 织梦文章页模板使用php语法,织梦文章页面模板顶一下踩一下调用教程
  6. 华为鲲鹏HCIA认证 常考题
  7. Python游戏开发实战:飞机大战(含代码)
  8. dbv工具连接oracle10g,10.2.2 DBV工具
  9. 我们学校有一个计算机室英文,深圳朗文版小学二年级下册Unit 2 At school练习题...
  10. 多媒体技术计算机系统由组成,多媒体技术概述及多媒体计算机系统的组成
  11. 【Python 基础教程】彻底解决python round函数的四舍五入不精确的问题
  12. 从菜鸟到架构师(三)
  13. 使用Mozilla Thunderbird 创建ics日历文件
  14. 技术人攻略访谈四十-刘睿民:数据库战国时代,我不跟你们玩政治!
  15. 梯度下降的超参数大于等于2什么意思_大白话5分钟带你走进人工智能-第七节梯度概念和梯度迭代过程(2)...
  16. linux屏幕亮度调整命令,linux下调节笔记本屏幕亮度方法-涉及命令lspci, setpci (转载)...
  17. java基于ssm的万卷图书馆借阅管理平台
  18. Egret蛮牛游戏引擎入门和开发(官方版)
  19. 有个程序员女朋友是什么体验?
  20. python网站设计开题报告_网站毕业设计开题报告范文

热门文章

  1. ELO rating system
  2. HTTP基础:接口测试
  3. 内存管理基本知识-大致
  4. python手册 apk_python apk
  5. 陶瓷基覆铜板性能要求与标准
  6. 适合零基础学习的IT编程技术
  7. oracle .bdb,crfclust.bdb文件过大的处理方法
  8. 步进电机失步(丢步)怎么解决?
  9. 市场营销Chapter02
  10. 脉冲信号是数字信号吗?为什么时间离散的信号在幅值上可以是连续的?