为什么打印1?

时间:2013-10-29 07:11:29

标签: java try-finally

我有代码:

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。

5 个答案:

答案 0 :(得分:6)

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

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


docs引用。这可以帮助您更清楚地理解它。

最后编译

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. 执行中断或继续声明
  4. 提出异常。

答案 1 :(得分:1)

这是因为try {catch}的finally块最终在try..catch内的代码完成后运行

您已在finally中分配了值,在此之前您已返回try

最终总是执行代码,但您已经返回try中的值。

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

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

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

现在return的{​​{1}}。

修改

您的怀疑:为什么不可能出现无法解决的错误?

10

块是不同的。在相同的块中执行相同操作并查看。

try-catch-finally

<强> EDIT2

来自java language specification of try-catch-finally :

  

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

答案 2 :(得分: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,因为最终不会更新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返回。

答案 3 :(得分: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 ...

答案 4 :(得分:0)

简单地说......您还没有在 < 之后提及返回 / strong>即可。 最后一个块在最后执行,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;
      }
    }
  }