其实return和finally的执行顺序问题非常简单,你只有看看代码的指令就清楚咯

简介: 看看代码的指令就清楚咯


image.png

  最近在整理Java常见的面试题,刚好整理到return和finally的执行顺序问题,这个很多小伙伴比较困惑,所以波波老师就通过指令带大家彻底弄清楚下

return和finally的顺序问题

  分析如下的代码程序,给出输出结果,并给出原因

public class Demo02 {
    public static void main(String[] args) {
        Demo02 demo02 = new Demo02();
        System.out.println(demo02.getName("bobo"));
    }
    public String getName(String name){
        String res = "";
        try {
            res = name;
            return  res;
        }finally {
            res = "波波烤鸭";
        }
    }
}

  输出的结果是:bobo

  原因:通过指令分析我们可以发现在 return 代码执行的时候会将局部变量保存在  栈帧的顶部,然后在finally中修改的还是原来的栈帧位置的局部变量,最终返回的信息还是栈帧顶部的变量,所以finally代码块在return关键字之后会执行,但是不会改变栈帧顶部的信息。

指令分析

  首先我们要清楚在jvm中,每个线程都具有自己的虚拟机栈。当执行方法时,如上面的getName,就会创建一个栈帧(存储局部变量表,操作数栈等信息)进入虚拟机栈。每一个方法从调用到执行完毕,就是一个栈帧从虚拟机栈中入栈到出栈的过程。对应的栈帧情况为

image.png

ldc:将int,float或者String类型常量从常量池推送至栈顶。

astore:将栈顶引用型类型数据存入指定本地变量。

aload:将制定的引用类型变量推送至栈顶

查看关键的指令为:

image.png

还有一种情况需要注意,如果finally和try块中都有return关键字会怎么样呢?

public class Demo02 {
    public static void main(String[] args) {
        Demo02 demo02 = new Demo02();
        System.out.println(demo02.getName("bobo"));
    }
    public String getName(String name){
        String res = "";
        try {
            res = name;
            return  res;
        }finally {
            res = "波波烤鸭";
            return res; // 指令中返回的就不是栈帧顶部的数据了 而是 res 对应的栈帧位置
        }
    }
}

image.png

  通过指令我们可以看到在finally中的return关键字的指令返回的就是finally中的局部变量的信息,可以理解为finally中的return会覆盖掉try块中的return逻辑。




相关文章
|
5月前
启动俩万报错异常处理
启动俩万报错异常处理
29 2
|
3月前
|
Rust 安全 程序员
|
6月前
|
JavaScript 前端开发 程序员
10个简单方法让你的代码更优雅
10个简单方法让你的代码更优雅
|
6月前
|
设计模式 消息中间件 前端开发
finally中的代码一定会执行吗?
finally中的代码一定会执行吗?
514 0
|
Oracle Java 关系型数据库
try-catch必须放在循环体外吗
try-catch必须放在循环体外吗
|
Web App开发 前端开发 JavaScript
重学前端 20 # try里面放return,finally还会执行吗?
重学前端 20 # try里面放return,finally还会执行吗?
134 0
重学前端 20 # try里面放return,finally还会执行吗?
线程的创建等待及退出 代码源码举例
线程的创建等待及退出 代码源码举例
76 0
|
Dart JavaScript
[Flutter]足够入门的Dart语言系列之流程控制语句:中断和异常(continue/break、try...catch)
循环的执行是通过循环条件来控制的,但是,有时我们想要通过额外的条件判断,来决定是否中断执行,或者中断本次循环而继续执行下次及之后的循环;此外,我们需要对于异常情况的处理...
453 0
[Flutter]足够入门的Dart语言系列之流程控制语句:中断和异常(continue/break、try...catch)
C# 错误CS0227 不安全代码只会在使用 /unsafe 编译的情况下出现
C# 错误CS0227 不安全代码只会在使用 /unsafe 编译的情况下出现
545 0
C# 错误CS0227 不安全代码只会在使用 /unsafe 编译的情况下出现