先来看一段关于Java fiannlly 的定义, 百度过来的:
finally通常和try/catch语句一起使用,确保了无论是否发生异常,finally里面的代码都会被执行。
关于这个定义,我想起来之前遇到的一个面试题,如果在try语句中return了,finally里面的代码还会执行么?
打印结果为:
try block
finally block
这说明了什么? 即使是在try语句中return了,finally里的代码依然会被执行到。
那么我就想到另一个问题,finally里的代码究竟是在return前执行的,还是在return后执行的?
我设计了这样一段代码:
究竟是先执行return 还是先执行finally呢?
结果是这样的:
try block
return statement
finally block
after return
可见是先调用了return的方法,然后才调用finally的代码。
这里就产生了一个悖论,既然某个方法已经return了,为什么还有代码继续执行呢?
我们看看产生的会编码:
仔细看这段:
也就是说,经过编译以后,代码变成了先调用test1,并存储返回值,然后调用finally里面的代码,最后才return。
这段代码似乎没有什么现实意义,不过还是可以对java程序的理解有一定的帮助。
finally通常和try/catch语句一起使用,确保了无论是否发生异常,finally里面的代码都会被执行。
关于这个定义,我想起来之前遇到的一个面试题,如果在try语句中return了,finally里面的代码还会执行么?
public static void main(String[] args) {
try {
System.out.println("try block");
return;
} finally {
System.out.println("finally block");
}
}
打印结果为:
try block
finally block
这说明了什么? 即使是在try语句中return了,finally里的代码依然会被执行到。
那么我就想到另一个问题,finally里的代码究竟是在return前执行的,还是在return后执行的?
我设计了这样一段代码:
public class Test {
public static void main(String[] args) {
System.out.println(test());
}
public static String test() {
try {
System.out.println("try block");
return test1();
} finally {
System.out.println("finally block");
}
}
public static String test1() {
System.out.println("return statement");
return "after return";
}
}
究竟是先执行return 还是先执行finally呢?
结果是这样的:
try block
return statement
finally block
after return
可见是先调用了return的方法,然后才调用finally的代码。
这里就产生了一个悖论,既然某个方法已经return了,为什么还有代码继续执行呢?
我们看看产生的会编码:
public class Test {
// Method descriptor #6 ()V
// Stack: 1, Locals: 1
public Test();
0 aload_0 [this]
1 invokespecial java.lang.Object() [8]
4 return
Line numbers:
[pc: 0, line: 2]
Local variable table:
[pc: 0, pc: 5] local: this index: 0 type: Test
// Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 2, Locals: 1
public static void main(java.lang.String[] args);
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 invokestatic Test.test() : java.lang.String [22]
6 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
9 return
Line numbers:
[pc: 0, line: 5]
[pc: 9, line: 6]
Local variable table:
[pc: 0, pc: 10] local: args index: 0 type: java.lang.String[]
// Method descriptor #25 ()Ljava/lang/String;
// Stack: 2, Locals: 2
public static java.lang.String test();
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 ldc <String "try block"> [34]
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
8 invokestatic Test.test1() : java.lang.String [36]
11 astore_1
12 getstatic java.lang.System.out : java.io.PrintStream [16]
15 ldc <String "finally block"> [39]
17 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
20 aload_1
21 areturn
22 astore_0
23 getstatic java.lang.System.out : java.io.PrintStream [16]
26 ldc <String "finally block"> [39]
28 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
31 aload_0
32 athrow
Exception Table:
[pc: 0, pc: 12] -> 22 when : any
Line numbers:
[pc: 0, line: 10]
[pc: 8, line: 12]
[pc: 12, line: 14]
[pc: 20, line: 12]
[pc: 22, line: 13]
[pc: 23, line: 14]
[pc: 31, line: 15]
// Method descriptor #25 ()Ljava/lang/String;
// Stack: 2, Locals: 0
public static java.lang.String test1();
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 ldc <String "return statement"> [41]
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
8 ldc <String "after return"> [43]
10 areturn
Line numbers:
[pc: 0, line: 19]
[pc: 8, line: 21]
}
仔细看这段:
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 ldc <String "try block"> [34]
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
8 invokestatic Test.test1() : java.lang.String [36]
11 astore_1
12 getstatic java.lang.System.out : java.io.PrintStream [16]
15 ldc <String "finally block"> [39]
17 invokevirtual java.io.PrintStream.println(java.lang.String) : void [26]
20 aload_1
21 areturn
也就是说,经过编译以后,代码变成了先调用test1,并存储返回值,然后调用finally里面的代码,最后才return。
这段代码似乎没有什么现实意义,不过还是可以对java程序的理解有一定的帮助。