【Java疑难杂症】有return的情况下try catch finally的执行顺序
有这样一个问题,异常处理大家应该都不陌生,类似如下代码:
 public class Test {
     public static void main(String[] args) {
         int d1 = 0;
         int d2 = 1;
         try {
             d2--;
             d1 = 1 / d2;
             System.out.println("try");
         }catch (Exception e){
             System.out.println("Catch An Exception.");
         }finally {
             System.out.println("finally");
         }
     }
 }
运行到第7行的时候,会出现算术异常,try语句块捕获到这个异常,然后开始执行catch语句块中的内容,最后执行,finally语句块中的内容,因此输出如下:
Catch An Exception.
finally
但是,如果try,catch,finally语句中有return的时候,会怎样呢?
我们都知道,finally语句块是不论如何都会执行的,那三个块中的return,会先返回谁呢?我们来进行一下测试:
public class Test {
    public static void main(String[] args) {
        int i = Test.getReturn();
        System.out.println(i);
    }
    public static int getReturn(){
        int a = 0;
        int d1 = 0;
        int d2 = 1;
        try {
      //try语句块中没有发生异常
            a = 10;
            d1 = 1 / d2;
            return a;
        }catch (Exception e){
            a = 20;
            System.out.println("Catch An Exception.");
            return a;
        }finally {
            a = 30;
            System.out.println("finally");
            return a;
        }
    }
}
这里的try语句块中没有发生异常,那么执行顺序如何呢?在try中的return是直接返回吗?finally的return该怎样处理呢?先让我们看一下结果:
finally
30
结果是执行完成finally语句块之后,使用的是finally语句块中的a,而不是try语句块中的a。
那如果try中出现异常呢?我们改动一下:
public class Test {
    public static void main(String[] args) {
        int i = getReturn();
        System.out.println(i);
    }
    public static int getReturn(){
        int a = 0;
        int d1 = 0;
        int d2 = 1;
        try {
            a = 10;
            d1 = 1 / (--d2);
            return a;
        }catch (Exception e){
            a = 20;
            System.out.println("Catch An Exception.");
            return a;
        }finally {
            a = 30;
            System.out.println("finally");
            return a;
        }
    }
}
好的,现在try中出现了算术异常,catch语句块将被执行,然后再执行finally语句块,这样的话返回结果如何呢?
Catch An Exception.
finally
30
还是返回30,也就是finally中a的值
如果去掉finally中的return会怎样?
public class Test {
    public static void main(String[] args) {
        int i = getReturn();
        System.out.println(i);
    }
    public static int getReturn(){
        int a = 0;
        int d1 = 0;
        int d2 = 1;
        try {
            a = 10;
            d1 = 1 / (--d2);
            return a;
        }catch (Exception e){
            a = 20;
            System.out.println("Catch An Exception.");
            return a;
        }finally {
            a = 30;
            System.out.println("finally");
            //return a;
        }
    }
}
输出如下:
Catch An Exception.
finally
20
返回的是catch语句块中的a。先执行catch语句块中的代码,finally语句虽然执行了,a的值应该也被修改成30了,但实际返回的却是20,。
我们再来做一个测试,把catch和finally语句块中的return都注释掉,来看看返回情况:
public class Test {
    public static void main(String[] args) {
        int i = getReturn();
        System.out.println(i);
    }
    public static int getReturn(){
        int a = 0;
        int d1 = 0;
        int d2 = 1;
        try {
            a = 10;
            d1 = 1 / (d2);
            return a;
        }catch (Exception e){
            a = 20;
            System.out.println("Catch An Exception.");
            //return a;
        }finally {
            a = 30;
            System.out.println("finally");
            //return a;
        }
        return a;
    }
}
输出如下:
finally
10
所以finally中虽然修改了a的值,但实际返回的是修改之前的值。也就是相当于程序先用一个瓶子将try中的return的值装起来,后面不管finally如果修改a的值,返回值都不会变,但这只是因为返回的是基本数据类型,如果是引用类型,还是有点区别的,来看个栗子。
先声明一个Stu类:
public class Stu {
    String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
测试一下:
public class Test {
    public static void main(String[] args) {
        Stu stu = getReturn();
        System.out.println(stu.getName());
    }
    public static Stu getReturn(){
        Stu stu = new Stu();
        int d1 = 0;
        int d2 = 1;
        try {
            stu.setName("1");
            d1 = 1 / (d2);
            return stu;
        }catch (Exception e){
            stu.setName("2");
            System.out.println("Catch An Exception.");
        }finally {
            stu.setName("3");
            System.out.println("finally");
        }
        return stu;
    }
}
输出如下:
finally
3
所以你看,现在还是变成了finally中的修改值,所以瓶子里装的只是变量中的内容,只能保证这个内容不会变,如果是引用变量,变量中存储的是引用对象的地址,finally中对引用对象的修改还是会影响到返回对象的。
所以结论其实很简单,try,catch,finally语句块的return的优先级由低到高,先执行try中return之前的语句,如果遇到异常,则执行catch语句中return之前的代码,最后执行finally语句块,finally语句块中如果有return,那么程序就会提前返回,如果没有,则返回catch语句块中的return,如果没有遇到异常,则直接执行finally中的语句块,再看finally语句块中是否有return来决定返回结果。
  结论:
  1、不管是否出现异常,finally块中的代码都会执行;
  2、当try和catch中有return时,finally仍然会执行,finally中的return优先级大于catch大于try;
  3、finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保存起来,管finally中的代码怎么样,返回的值都不会改变,任然是之前保存的值),所以函数返回值是在finally执行前确定的;
  4、finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值。
【Java疑难杂症】有return的情况下try catch finally的执行顺序的更多相关文章
- Java基础知识强化之IO流笔记06:有return的情况下try catch finally的执行顺序
		
1. 给出结论: (1)不管有木有出现异常,finally块中代码都会执行:(2)当try和catch中有return时,finally仍然会执行:(3)finally是在return后面的表达式运算 ...
 - 有return的情况下try catch finally的执行顺序(转)
		
结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
 - 有return的情况下try catch finally的执行顺序
		
结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
 - 有return的情况下try catch finally的执行顺序(最有说服力的总结)
		
结论:1.不管有木有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
 - 有return的情况下try catch finally的执行顺序(转)
		
结论:1.不管有没有出现异常,finally块中代码都会执行:2.当try和catch中有return时,finally仍然会执行:3.finally是在return后面的表达式运算后执行的(此时并没 ...
 - [转]有return的情况下try catch finally的执行顺序
		
结论: 1.不管有没有出现异常,finally块中代码都会执行: 2.当try和catch中有return时,finally仍然会执行: 3.finally是在return后面的表达式运算后执行的(此 ...
 - throw和throws的区别以及try,catch,finally在有return的情况下执行的顺序
		
一,抛出异常有三种形式,一是throw,一个throws,还有一种系统自动抛异常.下面它们之间的异同. (1).系统自动抛异常 1.当程序语句出现一些逻辑错误.主义错误或类型转换错误时,系统会自动抛出 ...
 - 【转】C# 异常处理 throw和throw ex的区别 try catch finally的执行顺序(return)
		
[转]throw和throw ex的区别 之前,在使用异常捕获语句try...catch...throw语句时,一直没太留意几种用法的区别,前几天调试程序时无意中了解到几种使用方法是有区别的,网上一查 ...
 - Java之HashMap在多线程情况下导致死循环的问题
		
PS:不得不说Java编程思想这本书是真心强大.. 学习内容: 1.HashMap<K,V>在多线程的情况下出现的死循环现象 当初学Java的时候只是知道HashMap<K,V& ...
 
随机推荐
- webpack-dev-server配置指南(使用webpack3.0)
			
最近正在研究webpack,听说webpack可以自己搭建一个小型的服务器(使用过vue-cli的朋友应该都见识到过),所以迫不及待的想要尝试一下.不过,在实际操作中发现,用webpack搭建服务器仍 ...
 - 2017值得一瞥的JavaScript相关技术趋势
			
2017值得一瞥的JavaScript相关技术趋势从属于笔者的Web 前端入门与工程实践,推荐阅读2016-我的前端之路:工具化与工程化获得更多关于2016年前端总结.本文主要内容翻译自,笔者对于每个 ...
 - CSS滤镜效果
			
使用 filter: blur() 生成毛玻璃效果 使用 filter: drop-shadow() 生成整体阴影效果 使用 filter: opacity() 生成透明度 blur生成阴影 通常我们 ...
 - 解决 Win10 UWP 无法使用 ss 连接
			
一旦使用了 ss, 那么很多应用就无法连接网络. 本文提供一个方法可以简单使用ss提供的代理. 多谢 wtwsgs 提供方法:http://blog.csdn.net/wtwsgs/article/d ...
 - Ubuntu15.04 网站服务器环境搭建,php/html/css等学习环境搭建教程
			
---恢复内容开始--- 本文部分参考自:http://www.cnblogs.com/emouse/archive/2013/06/07/3124009.html 原文中存在少量错误,已改正. 首先 ...
 - 《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结
			
前几天,个人著作<Unity3D/2D游戏开发从0到1(第二版)>经过七八个月的技术准备以及近3个月的日夜编写,在十一长假后终于完稿.今天抽出一点时间来,给广大热心小伙伴们汇报一下书籍概况 ...
 - javascript方法的方法名慎用close
			
通常我们在定义了与window同名的方法时,会自动覆盖掉window同名的方法.close()方法也不例外.示例: <!DOCTYPE html PUBLIC "-//W3C//DTD ...
 - json解析eval()中文乱码问题的解决
			
只需要后台post请求中添加: resp.setContentType("text/html;charset=utf-8"); req.setCharacterEncoding(& ...
 - 读书笔记-你不知道的JS中-函数生成器
			
这个坑比较深 可能写完我也看不懂(逃 ES6提供了一个新的函数特性,名字叫Generator,一开始看到,第一反应是函数指针?然而并不是,只是一个新的语法. 入门 简单来说,用法如下: functio ...
 - 读书笔记-你不知道的JS中-promise(2)
			
继续填坑 模式 考虑下面的代码: function fn(x) { //do something return new Promise(function(resolve, reject) { //调用 ...