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
*///:~

 

posted @ 2019-01-21 13:14  江期玉  阅读(1120)  评论(0编辑  收藏  举报