浅析Java try....catch....finally中return语句执行顺序

原创 2017年05月19日 22:59:14

浅析Java try….catch….finally中return语句执行顺序

最近看到一道JAVA笔试题:“try{..}中有return语句,那么紧跟在try后的finally{..}的code会不会执行,什么时候执行?”
finally内的code会执行,但是什么时候执行就难以确定,于是运行一段程序后觉得是在return语句执行后,return语句返回前执行,看代码清楚些

public class Test {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(new Test().test());
    }
    public int test(){
        int i=1;
        try{
            System.out.println("try....");
            return i+=2;
        }
        finally{
            System.out.println("finally....");
            i+=3;
            System.out.println(i);
        }
    }
}

运行结果:
try….
finally….
6
3
根据运行结果可知try{..}先运行,并且return后的expression:i+=2也运行了,此时i=3,再运行finally{…}的代码。此时i=6,但是返回的值却是3;
这就涉及到java方法在栈幀中执行过程,
具体参考http://blog.csdn.net/zq602316498/article/details/38926607
java方法是在栈帧中执行,栈帧是线程私有栈的单位,执行方法的线程会为每一个方法分配一小块栈空间来作为该方法执行时的内存空间,栈帧分为三个区域:
1. 操作数栈,用来保存正在执行的表达式中的操作数。
2. 局部变量区,用来保存方法中使用的变量,包括方法参数,方法内部声明的变量,以及方法中使用到的对象的成员变量或类的成员变量(静态变量),最后两种变量会复制到局部变量区。
3. 字节码指令区,这个不用解释了,就是方法中的代码翻译成的指令。
return语句
eturn expression是分成两部分执行的:
执行:expression;
执行:return指令;
例如:return x+y;
这句代码先执行x+y,再执行return;首先执行将x以及y从局部变量区复制到操作数栈顶的指令,然后执行加法指令,这个时候结果x+y的值会保存在操作数栈的栈顶,最后执行return指令,返回操作数栈顶的值。
如果方法中有finally语句块,那么return语句又是如何执行的呢?
例如下面这段代码:
try{
return expression;
}finally{
code…..;
}
首先我们知道,finally语句是一定会执行,但他们的执行顺序是怎么样的呢?他们的执行顺序如下:
1、expression,计算该表达式,结果保存在操作数栈顶;
2、操作数栈顶值(expression的结果)复制到局部变量区作为返回值;
3、finally语句块中的代码;
4、将第2步复制到局部变量区的返回值又复制回操作数栈顶;
5、return指令,返回操作数栈顶的值;
我们可以看到,在第一步执行完毕后,整个方法的返回值就已经确定了,由于还要执行finally代码块,因此程序会将返回值暂存在局部变量区,腾出操作数栈用来执行finally语句块中代码,等finally执行完毕,再将暂存的返回值又复制回操作数栈顶。所以无论finally语句块中执行了什么操作,都无法影响返回值,所以试图在finally语句块中修改返回值是徒劳的。因此,finally语句块设计出来的目的只是为了让方法执行一些重要的收尾工作,而不是用来计算返回值的。
所以运行结果返回值为3,而不是6。finally语句在return语句执行后,return语句返回前执行。

如果finally{….}中有return 语句呢?

public class Test {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(new Test().test());
    }
    public int test(){
        int i=1;
        try{
            System.out.println("try....");

            return i+=2;
        }
        finally{
            System.out.println("finally....");
            i+=3;
            System.out.println(i);
            return i;
        }
    }
}

运行结果:
try….
finally….
6
6
try中的return 被finally 中的return 覆盖。

如果catch{….}中有return 语句呢

public class Test {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(new Test().test());
    }
    public int test(){
        int i=1;
        try{
            System.out.println("try....");
            i/=0;
            i+=2;
            return i;
        }catch(Exception e){
            System.out.println("catch....");
            i+=1;
            return i;
        }
        finally{
            System.out.println("finally....");
            i+=3;
            System.out.println(i);
        }
    }

运行结果:
try….
catch….
finally….
5
2
先运行try{..},此时i/=0;抛出异常,catch捕捉异常并执行catch{…},执行return语句后,执行完finally{…},return 返回 i 值。并且 i 值不受finally的影响。

如果try….catch….finally中都有return语句呢

public class Test {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(new Test().test());
    }
    public int test(){
        int i=1;
        try{
            System.out.println("try....");
            i+=2;
            return i;
        }catch(Exception e){
            System.out.println("catch....");
            i+=1;
            return i;
        }
        finally{
            System.out.println("finally....");
            i+=3;
            System.out.println(i);
            return i;
        }
    }
}

运行结果
try….
finally….
6
6

public class Test {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println(new Test().test());
    }
    public int test(){
        int i=1;
        try{
            System.out.println("try....");
            i/=0;
            i+=2;
            return i;
        }catch(Exception e){
            System.out.println("catch....");
            i+=1;
            return i;
        }
        finally{
            System.out.println("finally....");
            i+=3;
            System.out.println(i);
            return i;
        }
    }
}

运行结果
try….
catch….
finally….
5
5
可以看出,不管有无异常,finally的return语句都会进行覆盖。
最后总结:finally块的语句在try或catch中的return语句执行之后返回之前执行,且finally里的修改语句可能影响也可能不影响try或catch中return已经确定的返回值,若finally里也有return语句则覆盖try或catch中的return语句直接返回

版权声明:本文为博主原创文章,未经博主允许不得转载。

try-catch语句中return和finally执行顺序详解

刷java面试题偶然看到这类问题(try/finally中含有return时的执行顺序),觉得挺有意思于是小小的研究了一下,希望经过我添油加醋天马行空之后,能给你带来一定的帮助 原题 try {...
  • zhoushumin157016
  • zhoushumin157016
  • 2017年06月15日 09:29
  • 518

Java异常捕获之try-catch-finally-return的执行顺序

情况1:try块中没有抛出异常try和finally块中都有return语句 public static int NoException(){ int i=10; try{ S...
  • aaoxue
  • aaoxue
  • 2013年01月23日 21:45
  • 11965

Java中try catch finally语句中含有return语句的执行情况(总结版)

在这里看到了try catch finally语句中含有return语句的几种总结情况,但其实解释的很含糊,而且并不全面。但有一点是可以肯定的,finally块中的内容会先于try中的 return...
  • mmc_maodun
  • mmc_maodun
  • 2013年12月25日 23:06
  • 12889

java中异常处理finally和return语句的执行顺序

finally代码块的语句在return之前一定会得到执行 如果try块中有return语句,finally代码块没有return语句,那么try块中的return语句在返回之前会先将要返回的值保存,...
  • shihui512
  • shihui512
  • 2016年06月14日 19:36
  • 1672

Java:类中代码的执行顺序

引言对于Java的初学者而言,很多时候我们只知道如何写一些基础的代码,但是却不知道为什么,对于一些概念而言,更是停留在一个很模糊的概念上,其实这样是不好的一种学习习惯。所以对于不太清楚的一些概念,自己...
  • wenwen091100304
  • wenwen091100304
  • 2015年10月29日 10:32
  • 7869

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

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

Java finally语句到底是在return之前还是之后执行?---第一篇

当return遇到finally 看过网上关于Java中异常捕获机制try…catch…finally块中的finally语句是不是一定会被执行的讨论也有很多。首先明确一点,下面两种情况finally...
  • loongshawn
  • loongshawn
  • 2016年01月09日 21:43
  • 924

java中finally与return的执行顺序详解

一些准备知识:     首先为了说明白java中finally与return的执行顺序是怎样的这个问题,我们需要做一点准备工作。     java方法是在栈幀中执行,栈幀是线程私有栈的单位,执行方法的...
  • qj19842011
  • qj19842011
  • 2015年05月12日 21:16
  • 5761

java for循环的执行顺序和几种常用写法

算是温习吧。问题比较基础,但是也比较重要。(虽然是C,但是很经典) for循环可以说在每个程序中都少不了的,语句头包括三个部分:初始化,判读条件,一个表达式。 但是这三个部分的执行顺序是什...
  • cs408
  • cs408
  • 2015年09月30日 08:58
  • 4387

java 内return语句总结

return 在Java中作用         根据《java编程思想:第四版》4.5节中介绍:return语句作为一个无条件的分支,无需判断条件即可发生。return语句主要有两个用途:一方面用来表...
  • wikiday
  • wikiday
  • 2013年07月15日 22:54
  • 7543
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:浅析Java try....catch....finally中return语句执行顺序
举报原因:
原因补充:

(最多只允许输入30个字)