java finally
一.使用finally进行清理
对于一些代码,可能会希望无论try块中的异常是否被抛出,它们都能得到执行,这通常适用于内存回收之外的情况(内存回收由垃圾回收器完成),为了达到这个效果,可以异常处理程序后面加上finally子句,完整的异常处理程序看起来像这样:
try{ // The guarded region: dangerous activities // that might throw A. B. or C } catch(A a1){ // Handler for situation A } catch(B b1){ //Handler for situation B } catch(C c1){ // Handler for situation C } finally{ //Activities that happen every time }
为了证明finaly总会被执行,可以试试下面的程序
package exceptions; //: exceptions/FinallyWorks.java // The finally clause is always executed. class ThreeException extends Exception {} public class FinallyWorks { static int count = 0; public static void main(String[] args) { while(true) { try { // Post-increment is zero first time: if(count++ == 0) throw new ThreeException(); System.out.println("No exception"); } catch(ThreeException e) { System.out.println("ThreeException"); } finally { System.out.println("In finally clause");//在异常被抛出是执行了一次,在System.out.println(Noexception")后又执行了一次 if(count == 2) break; // out of "while" } } } } /* Output: ThreeException In finally clause No exception In finally clause *///:~
可以看到无论异常是否被抛出,finally子句总会被执行.这个程序也给了我们一些思路,当java中的异常不允许我们回到异常抛出的地点,那么如何应对呢? 如果把try块放在循环里,就建立了一个"程序继续执行之前必须要达到"的条件,还可以加入static类型的计数器或者别的装置,使循环在放弃以前能尝试一定的次数,这将使程序的健壮性更上一个台阶
二. finally可以用来做什么
1.) Java中使用finally一般把除内存之外的资源恢复到它们的初始状态时.这种需要清理的资源包括:已经打开的文件或网络连接,在屏幕上画的图形,甚至可以是外部世界的某个开关
package exceptions; //: exceptions/Switch.java import static net.mindview.util.Print.*; public class Switch { private boolean state = false; public boolean read() { return state; } public void on() { state = true; print(this); } public void off() { state = false; print(this); } public String toString() { return state ? "on" : "off"; } } ///:~ package exceptions; //: exceptions/OnOffException1.java public class OnOffException1 extends Exception {} ///:~ package exceptions; //: exceptions/OnOffException2.java public class OnOffException2 extends Exception {} ///:~ package exceptions; //: 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();//异常未被捕获,sw.off没有执行 } catch(OnOffException2 e) { System.out.println("OnOffException2"); sw.off(); } } } /* Output: on off *///:~
程序的目的是确保main()结束时开关必须关闭,所以每个try块和异常处理程序的末尾都加入了对sw.off()方法的调用,但也可能异常被抛出,但没有被处理程序捕获,这是sw.off()就得不到调用,但有了finally,只要把try块中清理的代码移放到一起即可
package exceptions; //: 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(); } } } /* Output: on off *///:~
2. 异常处理机制会在跳到更高一层的异常处理程序之前,执行finall当涉及到break和continue语句时finally也会被执行
package exceptions; //: exceptions/AlwaysFinally.java // Finally is always executed. import static net.mindview.util.Print.*; class FourException extends Exception {} public class AlwaysFinally { public static void main(String[] args) { print("Entering first try block"); try { print("Entering second try block"); try { throw new FourException(); } finally { print("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"); } } } /* Output: Entering first try block Entering second try block finally in 2nd try block Caught FourException in 1st try block finally in 1st try block *///:~
三.在return中使用finally
1.) 因为finally子句总是会执行,所以在一个方法中,可以从多个点返回,并且可以保证重要清理工作仍旧会执行.从输出可以看出在fianlly类内部,从何处返回无关紧要,return语句返回之前会执行finally子句的代码块.
package exceptions; //: exceptions/MultipleReturns.java import static net.mindview.util.Print.*; public class MultipleReturns { public static void f(int i) { print("Initialization that requires cleanup"); try { print("Point 1"); if(i == 1) return; print("Point 2"); if(i == 2) return; print("Point 3"); if(i == 3) return; print("End"); return; } finally { print("Performing cleanup"); } } public static void main(String[] args) { for(int i = 1; i <= 4; i++) f(i); } } /* Output: Initialization that requires cleanup Point 1 Performing cleanup Initialization that requires cleanup Point 1 Point 2 Performing cleanup Initialization that requires cleanup Point 1 Point 2 Point 3 Performing cleanup Initialization that requires cleanup Point 1 Point 2 Point 3 End Performing cleanup *///:~