合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
### [finally 用来做什么?](https://lingcoder.gitee.io/onjava8/#/book/15-Exceptions?id=finally-%e7%94%a8%e6%9d%a5%e5%81%9a%e4%bb%80%e4%b9%88%ef%bc%9f) 对于没有垃圾回收和析构函数自动调用机制的语言来说,finally 非常重要。它能使程序员保证:无论 try 块里发生了什么,内存总能得到释放。但 Java 有垃圾回收机制,所以内存释放不再是问题。而且,Java 也没有析构函数可供调用。那么,Java 在什么情况下才能用到 finally 呢? 当要把除内存之外的资源恢复到它们的初始状态时,就要用到 finally 子句。这种需要清理的资源包括:已经打开的文件或网络连接,在屏幕上画的图形,甚至可以是外部世界的某个开关,如下面例子所示: ~~~ // exceptions/Switch.java public class Switch { private boolean state = false; public boolean read() { return state; } public void on() { state = true; System.out.println(this); } public void off() { state = false; System.out.println(this); } @Override public String toString() { return state ? "on" : "off"; } } // exceptions/OnOffException1.java public class OnOffException1 extends Exception {} // exceptions/OnOffException2.java public class OnOffException2 extends Exception {} // exceptions/OnOffSwitch.java // Why use finally? public class OnOffSwitch { private static Switch sw = new Switch(); public static void f() throws OnOffException1, OnOffException2 {} public static void main(String[] args) { try { sw.on(); // Code that can throw exceptions... f(); sw.off(); } catch(OnOffException1 e) { System.out.println("OnOffException1"); sw.off(); } catch(OnOffException2 e) { System.out.println("OnOffException2"); sw.off(); } } } ~~~ 输出为: ~~~ on off ~~~ 程序的目的是要确保 main() 结束的时候开关必须是关闭的,所以在每个 try 块和异常处理程序的末尾都加入了对 sw.off() 方法的调用。但也可能有这种情况:异常被抛出,但没被处理程序捕获,这时 sw.off() 就得不到调用。但是有了 finally,只要把 try 块中的清理代码移放在一处即可: ~~~ // exceptions/WithFinally.java // Finally Guarantees cleanup public class WithFinally { static Switch sw = new Switch(); public static void main(String[] args) { try { sw.on(); // Code that can throw exceptions... OnOffSwitch.f(); } catch(OnOffException1 e) { System.out.println("OnOffException1"); } catch(OnOffException2 e) { System.out.println("OnOffException2"); } finally { sw.off(); } } } ~~~ 输出为: ~~~ on off ~~~ 这里 sw.off() 被移到一处,并且保证在任何情况下都能得到执行。 甚至在异常没有被当前的异常处理程序捕获的情况下,异常处理机制也会在跳到更高一层的异常处理程序之前,执行 finally 子句: ~~~ // exceptions/AlwaysFinally.java // Finally is always executed class FourException extends Exception {} public class AlwaysFinally { public static void main(String[] args) { System.out.println("Entering first try block"); try { System.out.println("Entering second try block"); try { throw new FourException(); } finally { System.out.println("finally in 2nd try block"); } } catch(FourException e) { System.out.println( "Caught FourException in 1st try block"); } finally { System.out.println("finally in 1st try block"); } } } ~~~ 输出为: ~~~ Entering first try block Entering second try block finally in 2nd try block Caught FourException in 1st try block finally in 1st try block ~~~ 当涉及 break 和 continue 语句的时候,finally 子句也会得到执行。请注意,如果把 finally 子句和带标签的 break 及 continue 配合使用,在 Java 里就没必要使用 goto 语句了。