代码改变世界

《Java编程思想》之异常处理

2012-01-30 17:20  java线程例子  阅读(203)  评论(0编辑  收藏  举报

1、抛出异常之后

1).使用new在对象上创建异常对象

2).终止当前的执行路径

3).从当前环境中弹出对异常对象的引用

4).异常处理机制接管程序,并开始执行异常处理机制

2、异常处理理论上有两种基本模型

1).终止模型:一旦异常抛出,就表明错误无法挽回,也能回来继续执行。比较实用。

2).恢复模型:异常处理之后继续执行程序。但是可能导致“耦合”。

3、自定异常类(具有带参数的构造器)

class SimpleException extends Exception{
   public SimpleException(){}
   public SimpleException(String msg){
      super(msg);
   }
}
public class SimpleExceptionDemo{
   public void func() throws SimpleException{
      System.out.println("Throw SimpleExceptionfrom func().");
      throw new SimpleException();
   }
   public void func1() throws SimpleException{
      System.out.println("ThrowSimpleException from func1().");
      throw new SimpleException("Originated in func1()");
   }
   public static void main(String[] args){
      SimpleExceptionDemo sed = new SimpleExceptionDemo();
      try {
        sed.func();
      } catch (SimpleException e) {
        e.printStackTrace();
      }
      try {
        sed.func1();
      } catch (SimpleException e) {
        e.printStackTrace();
      }
   }
}

运行结果


4、异常说明:实用关键字throws,告知客户端程序员可能会抛出的异常类型。

5、在定义抽象基类和接口时,可以throws一些实际上并不抛出的异常。这样做的好处:为异常先占个位子,以后就可以抛出这种异常而不用修改已有的代码。

6、捕获所有异常(最好放在处理程序列表的末位):

catch (Exception e) {
   System.err.println("Caught an exception");
}

7、如果当前异常对象重新抛出,那么printStackTrace()方法显示的将是原来异常抛出点的调用栈信息,而非重新抛出点的信息。要想更新这个信息,可以调用fillInStackTrace()方法,这将返回一个Throwable对象,它是通过把当前调用栈信息填入原来那个异常对象而建立的。

8、

public static void main(String[] args) throws Throwable{
      try{
        throw new Throwable();
      }catch(Exception e){
        System.err.println("Caught inmain()");
      }
   }

因为Throwable是Exception的基类,所以下面程序中将不能再main()里捕获。

9、RuntimeException(或任何从它继承的异常)是一个特例,对于这种异常,编译器不需要异常说明。原因:

1).无法预料的错误。比如在你控制范围之外传递进来的null引用。

2).作为程序员,应该在代码中进行检查的错误。(比如对于ArrayIndexOutOfBoundsException,就得注意一下数组的大小了。)在一个地方发生的异常,常常会在另一个地方导致错误。

10、finally的作用:把除了内存之外的资源恢复到它们的初始状态。例如:已经打开的文件盒网络连接,在屏幕上画的图形,甚至可以是外部世界的某个开关。

11、异常丢失

class FirstException extends Exception{
   public String toString(){
      return "The firstException.";
   }
}
class SecondException extends Exception{
   public String toString(){
      return "The secondException.";
   }
}
 
public class ErrorFinally{
   void firstFunc() throws FirstException{
      throw new FirstException();
   }
   void secondFunc() throws SecondException{
      throw new SecondException();
   }
   public static void main(String[] args) throws Exception{
      ErrorFinally error = new ErrorFinally();
      try {
        error.firstFunc();
      } finally{
        error.secondFunc();
      }
   }
}

运行结果:


    可以看到,FirstException不见了,它被finally里的SecondException取代了。

12、异常的限制:当覆盖方法的时候,只能抛出在基类方法的异常说明里列出的那些异常。这个限制很有用,因为这意味着,当基类使用的代码应用到其派生类对象的时候,一样能够工作(当然,这是面向对象的基本概念),异常也不例外。

1).派生类构造函数的异常说明必须包含基类构造器的异常说明。

2).派生类构造器不能捕获基类构造器抛出的异常。(P275第三段最后一句怎么理解??)

3).派生类的方法可以不抛出异常,即使基类的方法有抛出异常。

4).派生类的方法可以抛出继承自"基类方法所抛出异常"的异常。

请看下面例子:

class BaseException extends Exception{}
class FuncException extends Exception{}
class OtherfuncException extends FuncException{}
class Base {
   Base() throws BaseException {
     
   }
   void func() throws FuncException {
      System.out.println("Base.func()");
   }
   void otherFunc() throws FuncException {
      System.out.println("Base.otherFunc()");
   }
}
public class InheritBase extends Base{
   //派生类构造函数的异常说明必须包含基类构造器的异常说明
   public InheritBase() throws BaseException {
      super();
   }
   //派生类的方法可以不抛出异常,即使基类的方法有抛出异常。
   void func(){
      System.out.println("InheritBase.func");
   }
   //派生类的方法可以抛出继承自"基类方法所抛出异常"的异常,如下OtherfuncException继承自FuncException
   //因为异常处理程序能捕获FuncException就一定能捕获OtherfuncException。
   void otherFunc() throws OtherfuncException{
      System.out.println("InheritBase.otherFunc()");
   }
   public static void main(String[] args){
      try {
        Base ib = new InheritBase();
        ib.func();
      } catch (BaseException e) {
        System.err.println("Caught BaseException.");
      } catch (FuncException e) {
        System.err.println("Caught funcException.");
      }
   }
}

13、把异常传给控制台

public static void main(String[] args) throws Exception{
     
}

14、把“被检查的异常”转换为“不检查的异常”:把“被检查的异常”这种功能给屏蔽掉。

1).

try {
       
} catch (BeCheckedException e) {
   throw new RuntimeException(e);
}

这样做的好处:不用“吐下”异常(“吐下”后异常完全消失),也不必把它放到方法的异常说明里(throws),而异常链还能保证你不会丢失任何原始异常的信息。

2).你也可以不写try-catch字句和/或异常说明,直接忽略异常,让它沿着调用栈往上“冒泡”。同时,还可以用getCause()捕获并处理特定的异常,如下例子:

class ZeroException extends Exception{}
class FirstException extends Exception{}
class secondException extends Exception{}
class SomeOtherException extends Exception{}
//把”被检查的异常“包装起来
class WrapCheckException{
   void throwRuntimeException(int type){
      try{
        switch(type){
           case 0: throw new ZeroException();
           case 1: throw new FirstException();
           case 2: throw new secondException();
           default: return;
        }
      }catch(Exception e){
        throw new RuntimeException(e);
      }
   }
}
public class TurnOffChecking{
   public static void main(String[] args){
      WrapCheckException wce = new WrapCheckException();
      wce.throwRuntimeException(3);
      for(int i = 0; i < 4; i++){
        try{
           if(i < 3)
              wce.throwRuntimeException(i);
           else
              throw new SomeOtherException();
        }catch(SomeOtherException e){
           System.out.println("SomeOtherException:" + e);
        }catch(RuntimeException e){
           try {
              //用getCause捕获特定异常
              throw e.getCause();
           } catch (ZeroException e1) {
              System.out.println("ZeroException:" + e1);
           } catch (FirstException e1) {
              System.out.println("FirstException:" + e1);
           } catch (secondException e1) {
              System.out.println("secondException:" + e1);
           } catch (Throwable e1) {
              System.out.println("Throwable:" + e1);
           }
        }
      }
   }
}

运行结果:


1).WrapCheckException. throwRuntimeException()把不同的异常包装进了RuntimeException对象。

2).可以不用try块就可以调用throwRuntimeException(),但是,也可以使用try块捕获你想捕获的异常。

3).程序中把getCause()的结果(也就是被包装的那个原始异常)抛出来,然后用它们自己的catch子句进行处理。

 以上内容整理自《Java编程思想》,若有遗漏,请您不吝指出。

觉得自己进度有点慢,多么想一口气把这本书看完。我还有几本?17天。现在才267页。我得加速!!