《关于 java 中 finally 语句块的深度辨析》由会员分享,可在线阅读,更多相关《关于 java 中 finally 语句块的深度辨析(14页珍藏版)》请在金锄头文库上搜索。
1、关于 Java 中 finally 语句块的深度辨析乍看这个题目,是不是有人会问,这个谁不知道啊,大凡熟悉 Java 编程的人都知道 finally 语句块的作用和用法。有什么可深度辨析的呢?事实并非如此,我发现即使写了很多年 Java 程序的人,也不一定能够透彻的理解 finally 语句块。本篇将以生动形象的案例来带您由浅入深的来分析一下这个小小的 finally,希望这篇文章能够让您真正的理解 finally 语句块的本质,至少阅读完本篇文章后,没有觉得浪费了时间。 可不能小看这个简单的 finally,看似简单的问题背后,却隐藏了无数的玄机。接下来我就带您一步一步的揭开这个 final
2、ly 的神秘面纱。问题分析首先来问大家一个问题:finally 语句块一定会执行吗?很多人都认为 finally 语句块是肯定要执行的,其中也包括一些很有经验的 Java 程序员。可惜并不像大多人所认为的那样,对于这个问题,答案当然是否定的,我们先来看下面这个例子。清单 1.public class Test public static void main(String args) System.out.println(return value of test(): + test(); public static int test() int i = 1; / if(i = 1) / retu
3、rn 0; System.out.println(the previous statement of try block); i = i / 0; try System.out.println(try block); return i; finally System.out.println(finally block); 清单 1 的执行结果如下:the previous statement of try block Exception in thread main java.lang.ArithmeticException: / by zero at com.bj.charlie.Test.
4、test(Test.java:15) at com.bj.charlie.Test.main(Test.java:6) 另外,如果去掉上例中被注释的两条语句前的注释符,执行结果则是:return value of test(): 0 在以上两种情况下,finally 语句块都没有执行,说明什么问题呢?只有与 finally 相对应的 try 语句块得到执行的情况下,finally 语句块才会执行。以上两种情况,都是在 try 语句块之前返回(return)或者抛出异常,所以 try 对应的 finally 语句块没有执行。那好,即使与 finally 相对应的 try 语句块得到执行的情况下,
5、finally 语句块一定会执行吗?不好意思,这次可能又让大家失望了,答案仍然是否定的。请看下面这个例子(清单 2) 。清单 2.public class Test public static void main(String args) System.out.println(return value of test(): + test(); public static int test() int i = 1; try System.out.println(try block); System.exit(0); return i; finally System.out.println(fin
6、ally block); 清单 2 的执行结果如下:try block finally 语句块还是没有执行,为什么呢?因为我们在 try 语句块中执行了 System.exit (0) 语句,终止了 Java 虚拟机的运行。那有人说了,在一般的 Java 应用中基本上是不会调用这个 System.exit(0) 方法的。OK !没有问题,我们不调用 System.exit(0) 这个方法,那么 finally 语句块就一定会执行吗?再一次让大家失望了,答案还是否定的。当一个线程在执行 try 语句块或者 catch 语句块时被打断(interrupted)或者被终止(killed) ,与其相对
7、应的 finally 语句块可能不会执行。还有更极端的情况,就是在线程运行 try 语句块或者 catch 语句块时,突然死机或者断电,finally 语句块肯定不会执行了。可能有人认为死机、断电这些理由有些强词夺理,没有关系,我们只是为了说明这个问题。回页首finally 语句剖析说了这么多,还是让我们拿出些有说服力的证据吧!还有什么证据比官方的文档更具说服力呢?让我们来看看官方网站上的The Java Tutorials中是怎样来描述 finally 语句块的吧!以下位于 * 之间的内容原封不动的摘自于 The Java Tutorials 文档。*The finally BlockThe
8、 finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling it allows the programmer to avoid having cleanup code accidentally bypassed by a return,continu
9、e, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.Note: If the JVM exits while the try or catch code is being executed, then the finally block may not execute. Likewise, if the thread executing the try or catch code is interrupted
10、 or killed, the finally block may not execute even though the application as a whole continues.*请仔细阅读并认真体会一下以上两段英文,当你真正的理解了这两段英文的确切含义,你就可以非常自信的来回答“finally 语句块是否一定会执行? ”这样的问题。看来,大多时候,并不是 Java 语言本身有多么高深,而是我们忽略了对基础知识的深入理解。接下来,我们看一下 finally 语句块是怎样执行的。在排除了以上 finally 语句块不执行的情况后,finally 语句块就得保证要执行,既然 final
11、ly 语句块一定要执行,那么它和 try 语句块与 catch 语句块的执行顺序又是怎样的呢?还有,如果 try 语句块中有 return 语句,那么 finally 语句块是在 return 之前执行,还是在 return 之后执行呢?带着这样一些问题,我们还是以具体的案例来讲解。关于 try、 catch、finally 的执行顺序问题,我们还是来看看权威的论述吧!以下 * 之间的内容摘自 Java 语言规范第四版( The Java Programming Language, Fourth Edition )中对于 try,catch,和 finally 的描述。*12.4. Try,
12、catch, and finallyYou catch exceptions by enclosing code in Try blocks. The basic syntax for a Try block is:try statements catch (exception_type1 identifier1) statements catch (exception_type2 identifier2) statements. finally statementswhere either at least one catch clause, or the finally clause, m
13、ust be present. The body of the try statement is executed until either an exception is thrown or the body finishes successfully. If an exception is thrown, each catch clause is examined in turn, from first to last, to see whether the type of the exception object is assignable to the type declared in
14、 the catch. When an assignable catch clause is found, its block is executed with its identifier set to reference the exception object. No other catch clause will be executed. Any number of catch clauses, including zero, can be associated with a particular TRy as long as each clause catches a differe
15、nt type of exception. If no appropriate catch is found, the exception percolates out of the try statement into any outer try that might have a catch clause to handle it.If a finally clause is present with a try, its code is executed after all other processing in the try is complete. This happens no matter how completion was achieved, whether normally, through an exception, or through a control flow statement such as return o