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

2022-08-31 07:42:02

我有一个简单的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 Block
dev  

为什么在块中没有被覆盖,但控制打印输出?sfinally


答案 1

块在执行语句时完成,执行语句时的值是方法返回的值。子句稍后更改的值(在语句完成后)这一事实不会(此时)更改返回值。tryreturnsreturnfinallysreturn

请注意,上面处理的是对块中自身值的更改,而不是对引用的对象的更改。如果 是对可变对象的引用(不是),并且该对象的内容在块中已更改,则这些更改将在返回值中看到。sfinallyssStringfinally

有关所有这些操作的详细规则,请参阅 Java 语言规范的第 14.20.2 节。请注意,语句的执行算作块的突然终止(以“如果由于任何其他原因 R....突然完成 try 块的执行”开头的部分适用)。请参阅 JLS 的第 14.17 节,了解为什么语句是块的突然终止。returntryreturn

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

如果块的执行由于任何其他原因R(除了引发异常之外)突然完成,则执行该块,然后有一个选择:tryfinally

  • 如果块正常完成,则语句由于原因 R 而突然完成。finallytry
  • 如果由于原因 S 而块突然完成,则语句由于原因 S 而突然完成(并且丢弃原因 R)。finallytry

结果是块中的语句确定整个语句的返回值,并且从块返回的值被丢弃。如果块引发异常,则语句中也会发生类似情况,它被块捕获,并且块和块都有语句。returnfinallytry-finallytrytry-catch-finallytrycatchcatchfinallyreturn


答案 2

因为返回值是在调用最终之前放在堆栈上的。


推荐