06 finally 中调整返回对象, 但是最终返回值未改变
Posted 蓝风9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了06 finally 中调整返回对象, 但是最终返回值未改变相关的知识,希望对你有一定的参考价值。
前言
// 回个家, 还什么都没有做, 各种各样的问题 ...
呵呵呵 很久以前的一个问题了, 当时写了 case, 但是 没有时间来看
并且 当时找了一下 jls 的相关说明, 也没有找到具体的 和 当前问题有关系的地方, 还是 理解能力不够
问题来自于 hllvmgroup [讨论] 关于try-finally编译, R 大也是做了比较详尽的说明
我们这里主要是 看一下 jls 中的说明, 以及 javac 中的一些具体的体现
引用 R大的一部分回复
RednaxelaFX 2013-06-21
直接在finally里用return语句可以干涉返回值,但只是改变显式的局部变量则不改变返回值。finally在执行时,语义上说那个try块里的return语句已经执行完了,只是控制流临返回之前进入finally块里转一圈而已。因而这个例子在实际javac实现中,try块里的return语句要返回的值被缓存在了一个编译器生成的局部变量里(slot 3),等实际返回的时候再拿出来。
slot 2则被用于临时存放try块里可能抛出的异常,用于在finally末尾重新抛出。
以下测试用例效果, 以及截图基于 jdk8
测试用例
测试用例来自于 原文章
/**
* FInallyUpdateReturnVal
*
* @author Jerry.X.He <970655147@qq.com>
* @version 1.0
* @date 2020-02-15 15:24
*/
public class Test20FinallyUdpateReturnVal
// Test20FinallyUdpateReturnVal
// https://hllvm-group.iteye.com/group/topic/38101
public static void main(String[] args)
System.out.println(get());
// get
public static String get()
String ret = "";
try
ret = "aa";
return ret;
finally
ret = "bb";
反编译的 class 的相关信息
master:21_javac jerry$ javap -c Test20FinallyUdpateReturnVal
Compiled from "Test20FinallyUdpateReturnVal.java"
public class Test20FinallyUdpateReturnVal
public Test20FinallyUdpateReturnVal();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: invokestatic #3 // Method get:()Ljava/lang/String;
6: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
9: return
public static java.lang.String get();
Code:
0: ldc #5 // String
2: astore_0
3: ldc #6 // String aa
5: astore_0
6: aload_0
7: astore_1
8: ldc #7 // String bb
10: astore_0
11: aload_1
12: areturn
13: astore_2
14: ldc #7 // String bb
16: astore_0
17: aload_2
18: athrow
Exception table:
from to target type
3 8 13 any
执行结果为, 呵呵 可能和我们常规的理解有一些差异, 为什么 finally 中的更新没有生效?
jls 关于 try-finally, return
14.20.2. Execution of try-finally and try-catch-finally
主要讲的是 try-fianlly & try-catch-finally 的相关约束, 和我们这里想要了解的说明是对不上的
主要讲的是 return 的相关约束, 下面有一些和 try-finally 相关的说明, 但是 和我们这里想要了解的说明是对不上的
javac 中的体现
可以看到这里在 "return ret" 生成 code 的时候, 发现 return 携带有 finally, 就生成了一个 临时变量来存储结果
然后执行 finally, 然后 加载 临时变量 返回
get 方法的 code 信息, code.cp 是 12, 表示 areturn 之前的内容有 12 字节
public static java.lang.String get();
Code:
0: ldc #5 // String
2: astore_0
3: ldc #6 // String aa
5: astore_0
6: aload_0
7: astore_1
8: ldc #7 // String bb
10: astore_0
11: aload_1
12: areturn
13: astore_2
14: ldc #7 // String bb
16: astore_0
17: aload_2
18: athrow
Exception table:
from to target type
3 8 13 any
完
参考
以上是关于06 finally 中调整返回对象, 但是最终返回值未改变的主要内容,如果未能解决你的问题,请参考以下文章