-1

我有代码:

class Test {
  public static void main(final String [] args) {
    System.out.println(foo());
  }

  private static int foo() {
    int a = 0;
      try {
        ++a;
        return a;
      } finally {
        a = 10;
      }
    }
  }

我不明白为什么要打印 1 。

4

5 回答 5

6
try {
    ++a;
    return a; // 1 is returned here
} finally {
    a = 10; // a is assigned with 10 later.
}

的值a递增并在try块本身中返回。发布 this return, 的值在块a中重新分配。finally这就是为什么它打印1的原因。


文档中引用。这应该可以帮助您更清楚地理解它。

最后编译

try-finally 语句的编译类似于 try-catch。在将控制权转移到 try 语句之外之前,无论该转移是正常的还是突然的,因为抛出了异常,都必须首先执行 finally 子句。对于这个简单的例子:

void tryFinally() {
    try {
        tryItOut();
    } finally {
        wrapItUp();
    }
}

编译后的代码是:

Method void tryFinally()
0   aload_0             // Beginning of try block
1   invokevirtual #6    // Method Example.tryItOut()V
4   jsr 14              // Call finally block
7   return              // End of try block
8   astore_1            // Beginning of handler for any throw
9   jsr 14              // Call finally block
12  aload_1             // Push thrown value
13  athrow              // ...and rethrow value to the invoker
14  astore_2            // Beginning of finally block
15  aload_0             // Push this
16  invokevirtual #5    // Method Example.wrapItUp()V
19  ret 2               // Return from finally block
Exception table:
From    To      Target      Type
0       4       8           any

有四种方法可以在 try 语句之外传递控制:

  1. 通过从那个街区的底部掉下来
  2. 通过返回
  3. 通过执行 break 或 continue 语句
  4. 通过引发异常。
于 2013-10-29T07:12:20.467 回答
1

发生这种情况是因为finallytry..catch..finally 的块在代码try..catch完成后运行

您被分配了在finally您返回之前和之前的值try

finally 中的代码总是会执行,但是你已经返回了try.

try {
    ++a;
    return a; 
  } finally {
    a = 10; 
  }

现在的a值是10,之后的return。虽然不是一个好习惯,但只是为了演示。

int a= 0;
try {
    ++a;
    return a; 
  } finally {
    a = 10;
    return a;
  }

现在return10

编辑:

您的疑问:为什么无法实现的错误不会出现?

try-catch-finally块是不同的。在同一个块中做同样的事情,看看。

try {
            ++a;
            return a;
            a=100;  //compiler error.
          } finally {
            a = 10;
          }

编辑2

来自try-catch-finally 的 java 语言规范:

try 语句执行一个块。如果抛出一个值并且 try 语句有一个或多个可以捕获它的 catch 子句,则控制将转移到第一个这样的 catch 子句。如果 try 语句有 finally 子句,则执行另一个代码块,不管 try 块是正常完成还是突然完成,也不管 catch 子句是否首先被赋予控制权。

于 2013-10-29T07:12:53.827 回答
0
class Test {
  public static void main(final String [] args) {
    System.out.println(foo());
  }

  private static int foo() {
    int a = 0;
      try {
        ++a;
        return a;
      } finally {
        a = 10;
      }
    }
  }

在上面的代码中,返回值将是 1,因为 finally 不会更新 try 块中返回的值。

class Test {
  public static void main(final String [] args) {
    System.out.println(foo());
  }

  private static int foo() {
    int a = 0;
      try {
        ++a;
        return a;
      } finally {
        a = 10;
    return a;
      }
    }
  }

上面的代码将返回值为 10,因为该值又是从 finally 返回的。

于 2013-10-29T07:24:11.330 回答
0

简单地说......你没有提到return a in或 after final block。最终块在最后执行,a 的值设置为 10,但您还没有编写代码来返回这个新值!尝试以下代码以获得预期的输出:

class Test {
  public static void main(final String [] args) {
    System.out.println(foo());
  }

  private static int foo() {
    int a = 0;
      try {
        ++a;
        return a;
      } finally {
        a = 10;
       return a;
      }
    }
  }
于 2013-10-30T07:32:03.630 回答
0

JVM 是基于堆栈的机器。它将值推送和弹出到堆栈上。我反编译Test了类,以了解它是如何工作的。

private static int foo();
 Code:
   0: iconst_0        //push 0 to stack
   1: istore_0        //store 0 in the local variable 'a'(numbered 0). a==0
   2: iinc      0, 1  //increase the local variable 'a'(numbered 0) by 1. a==1;
   5: iload_0         //push value of the local variable 'a' onto the stack;
   6: istore_1        //store 1 in the local variable that not be declared(numbered 1);
   7: bipush    10    //push 10 onto the stack;
   9: istore_0        //store 10 in the local variable 'a'
  10: iload_1         //push onto stack value==1 of local variable that not be declared
  11: ireturn         //return 1
  12: astore_2
  13: bipush   10
  15: istore_0
  16: aload_2
  17: athrow
 Exception table:
 // not interesting ...
于 2013-10-30T07:20:45.317 回答