我有代码:
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。
答案 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 :(得分: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;
}
}
}