一.使用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总会被执行,可以试试下面的程序
packageexceptions;//: exceptions/FinallyWorks.java//The finally clause is always executed.
class ThreeException extendsException {}public classFinallyWorks {static int count = 0;public static voidmain(String[] args) {while(true) {try{//Post-increment is zero first time:
if(count++ == 0)throw newThreeException();
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一般把除内存之外的资源恢复到它们的初始状态时.这种需要清理的资源包括:已经打开的文件或网络连接,在屏幕上画的图形,甚至可以是外部世界的某个开关
packageexceptions;//: exceptions/Switch.java
import static net.mindview.util.Print.*;public classSwitch {private boolean state = false;public boolean read() { returnstate; }public void on() { state = true; print(this); }public void off() { state = false; print(this); }public String toString() { return state ? "on" : "off"; }
}///:~
packageexceptions;//: exceptions/OnOffException1.java
public class OnOffException1 extends Exception {} ///:~
packageexceptions;//: exceptions/OnOffException2.java
public class OnOffException2 extends Exception {} ///:~
packageexceptions;//: exceptions/OnOffSwitch.java//Why use finally?
public classOnOffSwitch {private static Switch sw = newSwitch();public static voidf()throwsOnOffException1,OnOffException2 {}public static voidmain(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块中清理的代码移放到一起即可
packageexceptions;//: exceptions/WithFinally.java//Finally Guarantees cleanup.
public classWithFinally {static Switch sw = newSwitch();public static voidmain(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也会被执行
packageexceptions;//: exceptions/AlwaysFinally.java//Finally is always executed.
import static net.mindview.util.Print.*;class FourException extendsException {}public classAlwaysFinally {public static voidmain(String[] args) {
print("Entering first try block");try{
print("Entering second try block");try{throw newFourException();
}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子句的代码块.
packageexceptions;//: exceptions/MultipleReturns.java
import static net.mindview.util.Print.*;public classMultipleReturns {public static void f(inti) {
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 voidmain(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*///:~