关于try catch:java:try finally块执行

java: try finally blocks execution

本问题已经有最佳答案,请猛点这里访问。

当try块中存在return;时,我对try finally执行感到困惑。在我的理解中,finally块将始终被执行,即在返回调用方法之前。同时考虑以下简单代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TryCatchTest {
    public static void main(String[] args){
        System.out.println(test());
    }
    static int test(){
        int x = 1;
        try{
            return x;
        }
        finally{
            x = x + 1;
        }
    }
}

打印的结果实际上是1。这是否意味着未执行finally块?有人能帮我吗?


try块返回时,返回值存储在该方法的堆栈帧中。然后执行finally块。

更改finally块中的值不会更改堆栈上已有的值。但是,如果您再次从finally块返回,堆栈上的返回值将被覆盖,新的x将被返回。

如果在finally块中打印x的值,您将知道它已执行,并且将打印x的值。

1
2
3
4
5
6
7
8
9
10
static int test(){
    int x = 1;
    try{
        return x;
    }
    finally{
        x = x + 1;
        System.out.println(x);  // Prints new value of x
    }
}


注意:如果返回引用值,则引用值存储在堆栈上。在这种情况下,可以使用该引用更改对象的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
StringBuilder builder = new StringBuilder("");
try {
    builder.append("Rohit");
    return builder;

} finally {
    // Here you are changing the object pointed to by the reference
    builder.append("Jain");  // Return value will be `Rohit Jain`

    // However this will not nullify the return value.
    // The value returned will still be `Rohit Jain`
    builder =  null;
}

建议阅读:

  • JVM规范-框架


最后一个块被执行。局部变量递增。但该局部变量的值已经为返回值复制。

从Java语言规范,14.17:返回语句:

A return statement with an Expression attempts to transfer control to the invoker
of the method that contains it; the value of the Expression becomes the value of
the method invocation.

...

The preceding descriptions say"attempts to transfer control" rather than just"transfers
control" because if there are any try statements (§14.20) within the method or constructor
whose try blocks or catch clauses contain the return statement, then any finally
clauses of those try statements will be executed, in order, innermost to outermost, before
control is transferred to the invoker of the method or constructor. Abrupt completion of a
finally clause can disrupt the transfer of control initiated by a return statement


退出前返回x。我会这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TryCatchTest {
    public static void main(String[] args) {
        System.out.println(test());
    }
    static int test() {
        int x = 1;
        try {
            do something with x.
        } finally {
            do something that will happen even in case of error;
            x = x + 1;
            return x;
        }
    }
}