为了账号安全,请及时绑定邮箱和手机立即绑定

为什么更改finally块中的返回变量不会更改返回值?

为什么更改finally块中的返回变量不会更改返回值?

波斯汪 2019-08-16 15:49:19
为什么更改finally块中的返回变量不会更改返回值?我有一个简单的Java类,如下所示:public class Test {     private String s;     public String foo() {         try {             s = "dev";             return s;         }          finally {             s = "override variable s";             System.out.println("Entry in finally Block");           }     }     public static void main(String[] xyz) {         Test obj = new Test();         System.out.println(obj.foo());     }}这段代码的输出是这样的:Entry in finally Blockdev为什么s不在finally块中覆盖,而是控制打印输出?
查看完整描述

3 回答

?
小怪兽爱吃肉

TA贡献1852条经验 获得超1个赞

try块在执行return语句s时完成,return语句执行时的值是方法返回的值。该finally子句稍后更改s(在return语句完成之后)的值不会(在该点)更改返回值。

请注意,上述内容涉及块中s自身值的更改finally,而不是s引用的对象。如果s是对可变对象的引用(String不是)并且在块中更改了对象的内容finally,那么将在返回的值中看到这些更改。

有关所有这些操作的详细规则可以在Java语言规范的第14.20.2节中找到。请注意,return语句的执行计为try块的突然终止(开始的部分“ 如果执行块因任何其他原因而突然完成R .... ”适用)。有关语句突然终止块的原因,请参见JLS的第14.17节return

通过进一步的细节:如果语句的try块和finally块都try-finallyreturn语句而突然终止,那么§14.20.2中的以下规则适用:

如果try由于任何其他原因R [除了抛出异常]而突然完成finally块的执行,则执行该块,然后有一个选择:

  • 如果finally块正常完成,则try语句突然完成,原因是R.

  • 如果finally块因原因S而突然完成,则try语句突然完成,原因为S(并且原因R被丢弃)。

结果是块中的return语句finally确定整个try-finally语句的返回值,并且try丢弃块中返回的值。try-catch-finally如果try块抛出异常,它会被catch块捕获,并且catch块和finally块都有return语句,那么在语句中会发生类似的事情。


查看完整回答
反对 回复 2019-08-16
?
慕运维8079593

TA贡献1876条经验 获得超5个赞


因为返回值在调用finally之前放在堆栈上。


查看完整回答
反对 回复 2019-08-16
?
子衿沉夜

TA贡献1828条经验 获得超3个赞

如果我们查看字节码内部,我们会注意到JDK已经进行了重大优化,而foo()方法看起来像:


String tmp = null;

try {

    s = "dev"

    tmp = s;

    s = "override variable s";

    return tmp;

} catch (RuntimeException e){

    s = "override variable s";

    throw e;

}

和字节码:


0:  ldc #7;         //loading String "dev"

2:  putstatic   #8; //storing it to a static variable

5:  getstatic   #8; //loading "dev" from a static variable

8:  astore_0        //storing "dev" to a temp variable

9:  ldc #9;         //loading String "override variable s"

11: putstatic   #8; //setting a static variable

14: aload_0         //loading a temp avariable

15: areturn         //returning it

16: astore_1

17: ldc #9;         //loading String "override variable s"

19: putstatic   #8; //setting a static variable

22: aload_1

23: athrow

java保留“dev”字符串在返回之前被更改。事实上,这根本没有最终阻止。



查看完整回答
反对 回复 2019-08-16
  • 3 回答
  • 0 关注
  • 868 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信