搜索
首页Javajava教程Java中return和finally语句的执行顺序是怎样的?

源码:

public class ReturnFinallyDemo {     public static void main(String[] args) {         System.out.println(case1());     }      public static int case1() {         int x;         try {             x = 1;             return x;         } finally {             x = 3;         }     } }  # 输出

上述代码的输出可以简单地得出结论:return在finally之前执行,我们来看下字节码层面上发生了什么事情。下面截取case1方法的部分字节码,并且对照源码,将每个指令的含义注释在后面:

iconst_1 // 将常量1推入操作数栈顶  istore_0 // 弹出栈顶元素(1),保存到局部变量表slot[0],此时slot[0]=1。这两条指令对应源码:x = 1;  iload_0 // 将局部变量表slot[0]的值推入操作数栈顶,也就是说把上面x的值推入栈顶  istore_1 // 弹出栈顶元素(1),保存到局部变量表slot[1],此时slot[1]=1。其实,此时就已经把要return的值准备好了  iconst_3 // 将常量3推入操作数栈顶,这一条指令开始,其实是开始执行finally中的代码了  istore_0 // 弹出栈顶元素(3),保存到局部变量表slot[0],此时slot[0]=3。这两个指令对应源码:x = 3;这里要注意的是,虽然都是更新了x的值,但是finally中的x和try中x的赋值,保存在了不同的局部变量表中 iload_1 // 将局部变量表slot[1]的值推入操作数栈顶,此时栈顶元素的值为1,是第3行指令保存的值  ireturn // 将操作数栈顶的值返回给调用方

从字节码来看,似乎又是finally的代码先执行了,因为ireturn指令确实是在最后执行的,所以返回什么样的值不在于谁先执行,而在于ireturn指令返回的操作数栈顶的元素是何时保存的。在上述代码环境中,是try代码块中给x赋值的版本,也就是紧接着return语句后面的x所保存的版本。

下面再来看一个稍微复杂点的场景:

public static int case2() {     int x;     try {         x = 1;         return ++x;     } finally {         x = 3;     } }  # 输出

有了上面的分析,这个就很好理解了,我们还是来看下字节码:

iconst_1 // 将常量1推入操作数栈顶 istore_0 // 弹出栈顶元素(1),保存到局部变量表slot[0],此时slot[0]=1。这两条指令对应源码:x = 1; iinc          0, 1 // 对局部变量表slot[0]进行自增(+1)操作,此时slot[0]=2,对应源码:++x;所以,可以看出return后面的表达式先执行 iload_0 // 将局部变量表slot[0]的值推入操作数栈顶,也就是说把上面x的值(2)推入栈顶 istore_1 // 弹出栈顶元素(2),保存到局部变量表slot[1],此时slot[1]=2。其实,此时就已经把要return的值准备好了 iconst_3 // 将常量3推入操作数栈顶,这一条指令开始,其实是开始执行finally中的代码了 istore_0 // 弹出栈顶元素(3),保存到局部变量表slot[0],此时slot[0]=3。这两个指令对应源码:x = 3;这里要注意的是,虽然都是更新了x的值,但是finally中的x和try中x的赋值,保存在了不同的局部变量表中 iload_1 // 将局部变量表slot[1]的值推入操作数栈顶,此时栈顶元素的值为2,是第6行指令保存的值,也就是经过++x之后的值 ireturn // 将操作数栈顶的值返回给调用方

从上述代码可以看出,return后面的指令先执行,然后保存到局部变量表,接着执行finally中的语句,最后执行return指令本身。

总结一下,return指令是最后执行的,如果return后面有表达式,则执行完表达式之后就执行finally中的语句,最后再执行return指令。所以说finally和return到底哪个先执行:return指令后面如果有表达式或方法调用的话,先执行,然后执行finally,最后执行return指令。就像上面的程序演示的结果,不能光从x的赋值来看最终返回结果,从指令层面看,两次对x的赋值,保存在局部变量表的位置不一样。

最后,再来看一个平时不会这么去写的场景:

public static int case3() {     int x;     try {         x = 1;         return ++x;     } finally {         x = 3;         return x;     } } # 输出

这是一个finally返回结果的示例,平时不建议这么写,我们同样从字节码的角度来分析下:

iconst_1 // 将常量1推入操作数栈顶 istore_0 // 弹出栈顶元素(1),保存到局部变量表slot[0],此时slot[0]=1。这两条指令对应源码:x = 1; iinc          0, 1 // 对局部变量表slot[0]进行自增(+1)操作,此时slot[0]=2,对应源码:++x;所以,可以看出return后面的表达式先执行 iload_0  // 将局部变量表slot[0]的值推入操作数栈顶,也就是说把上面x的值(2)推入栈顶 istore_1 // 弹出栈顶元素(2),保存到局部变量表slot[1],此时slot[1]=2。 iconst_3 // 将常量3推入操作数栈顶,这一条指令开始,其实是开始执行finally中的代码了 istore_0 // 弹出栈顶元素(3),保存到变量表slot[0],此时slot[0]=3。这两个指令对应源码:x = 3 iload_0  // 将局部变量表slot[0]的值(3)推入操作数栈,这是跟之前不一样的地方,ireturn返回的值选择的局部变量表不一样 ireturn

以上是Java中return和finally语句的执行顺序是怎样的?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:亿速云。如有侵权,请联系admin@php.cn删除
Java平台独立性:与不同的操作系统的兼容性Java平台独立性:与不同的操作系统的兼容性May 13, 2025 am 12:11 AM

JavaachievesPlatFormIndependencethroughTheJavavIrtualMachine(JVM),允许Codetorunondifferentoperatingsystemsswithoutmodification.thejvmcompilesjavacodeintoplatform-interploplatform-interpectentbybyteentbytybyteentbybytecode,whatittheninternterninterpretsandectectececutesoneonthepecificos,atrafficteyos,Afferctinginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginginging

什么功能使Java仍然强大什么功能使Java仍然强大May 13, 2025 am 12:05 AM

JavaispoperfulduetoitsplatFormitiondence,对象与偏见,RichstandardLibrary,PerformanceCapabilities和StrongsecurityFeatures.1)Platform-dimplighandependectionceallowsenceallowsenceallowsenceallowsencationSapplicationStornanyDevicesupportingJava.2)

顶级Java功能:开发人员的综合指南顶级Java功能:开发人员的综合指南May 13, 2025 am 12:04 AM

Java的顶级功能包括:1)面向对象编程,支持多态性,提升代码的灵活性和可维护性;2)异常处理机制,通过try-catch-finally块提高代码的鲁棒性;3)垃圾回收,简化内存管理;4)泛型,增强类型安全性;5)ambda表达式和函数式编程,使代码更简洁和表达性强;6)丰富的标准库,提供优化过的数据结构和算法。

Java真的平台独立吗? '写一次,在任何地方运行”如何起作用Java真的平台独立吗? '写一次,在任何地方运行”如何起作用May 13, 2025 am 12:03 AM

javaisnotirelyPlatemententduetojvmvariationsandnativecodinteintration,butitlargelyupholdsitsitsworapromise.1)javacompilestobytecoderunbythejvm

揭示JVM:您了解Java执行的关键揭示JVM:您了解Java执行的关键May 13, 2025 am 12:02 AM

thejavavirtualmachine(JVM)IsanabtractComputingmachinecrucialforjavaexecutionasitrunsjavabytecode,使“ writeononce,runanywhere”能力

Java仍然是基于新功能的好语言吗?Java仍然是基于新功能的好语言吗?May 12, 2025 am 12:12 AM

Javaremainsagoodlanguageduetoitscontinuousevolutionandrobustecosystem.1)Lambdaexpressionsenhancecodereadabilityandenablefunctionalprogramming.2)Streamsallowforefficientdataprocessing,particularlywithlargedatasets.3)ThemodularsystemintroducedinJava9im

是什么使Java很棒?关键特征和好处是什么使Java很棒?关键特征和好处May 12, 2025 am 12:11 AM

Javaisgreatduetoitsplatformindependence,robustOOPsupport,extensivelibraries,andstrongcommunity.1)PlatformindependenceviaJVMallowscodetorunonvariousplatforms.2)OOPfeatureslikeencapsulation,inheritance,andpolymorphismenablemodularandscalablecode.3)Rich

前5个Java功能:示例和解释前5个Java功能:示例和解释May 12, 2025 am 12:09 AM

Java的五大特色是多态性、Lambda表达式、StreamsAPI、泛型和异常处理。1.多态性让不同类的对象可以作为共同基类的对象使用。2.Lambda表达式使代码更简洁,特别适合处理集合和流。3.StreamsAPI高效处理大数据集,支持声明式操作。4.泛型提供类型安全和重用性,编译时捕获类型错误。5.异常处理帮助优雅处理错误,编写可靠软件。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

MinGW - 适用于 Windows 的极简 GNU

MinGW - 适用于 Windows 的极简 GNU

这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

SecLists

SecLists

SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。