和风细雨

世上本无难事,心以为难,斯乃真难。苟不存一难之见于心,则运用之术自出。

异常机制概述

异常机制综述

在运行过程中,应用程序可能遭遇各种严重程度不同的问题.异常提供了一种在不弄乱程序的情况下检查错误的巧妙方式.它也提供了一种直接报告错误的机制,而不必检查标志或者具有此作用的域.异常把方法能够报告的错误作为方法约定的一个显式部分.
异常能够被程序员看到,由编译器检查,并且由重载方法的子类保留.
如果遇到意外的错误将抛出异常,然后异常被方法调用栈上的子句捕获.如果异常未被捕获,将导致执行线程的终止.

异常的体系结构

毫无疑问,在java中异常是对象,它必定继承Throwable及其子类.Throwable中含有一个用于描述异常的字符串.Exception是Throwable的一个最常用子类,另一个子类是Error.而RuntimeException继承自Exception.


异常的种类

非检查型异常(Unchecked Exception):
非检查型异常反映了程序中的逻辑错误,不能从运行中合理恢复.
标准的运行时异常和错误构成非检查型异常,它们继承自RuntimeException和Error.
非检查型异常不用显示进行捕获.

检查型异常(Checked Exception):
这种异常描述了这种情况,虽然是异常的,但被认为是可以合理发生的,如果这种异常真的发生了,必须调用某种方法处理.
Java异常大多是检查型异常,继承自Exception类,你自己定义的异常必须是继承Exception的检查型异常.
检查型异常必须进行显示捕获.

自定义异常

继承Exception即可定义自己的异常,以下是一种常见写法
public class DBXmlFileReadException extends Exception{
  public DBXmlFileReadException(String   msg){
    super(msg);
  }
}

抛出异常

在Java语句中,可以用throw语句抛出异常,如throw new NoSuchElementException();
抛出的对象必须是Throwable类的子类型.

抛出异常的策略:
1) 如果抛出后不可能得到处理,可以抛出Error.
2) 如果你想让其它类自由选择是否处理这个异常,就可以抛出RuntimeException.
3) 如果你要求类的用户必须处理这个异常,则可以抛出Exception.

异常抛出后的控制权转移

一旦发生异常,异常发生点后的动作将不会发生.此后将要发生的操作不是在catch块和finally块.

当异常抛出时,导致异常发生的语句和表达式就被称为突然完成.语句的突然完成将导致调用链逐渐展开,直到该异常被捕获.

如果该异常没有捕获,执行线程将中止.

Try,catch和finally

异常由包含在try块中的语句捕获:
    try{
      正常执行语句
    }
    catch(XException e){
      异常执行语句一
    }
    catch(XXException e){
      异常执行语句二
    }
    catch(XXXException e){
      异常执行语句三
    }
    finally{
      中止语句
    }

Try中的语句体要么顺利完成,要么执行到抛出异常.
如果抛出异常,就要找出对应于异常类或其父类的catch子句,如果未能找到合适的catch子句,异常就从try语句中扩散出来,进入到外层可能对它进行处理的try语句.
Catch子句可以有多个,只要这些子句捕获的异常类型不同.
如果在try中有finally子句,其代码在try把所有其它处理完成之后执行.
无论是正常完成或是出现异常,甚至是通过return或者break这样的控制语句结束,finally子句总是被执行.
Catch子句和finally子句在try语句之后至少有一个,不要求全部出现.

More…

在catch语句中捕获通用的异常Exception通常不是最佳策略,因为它会将所有异常进行等同处理.
不能把基类异常的catch语句放到子类异常的catch语句之前,编译器会在运行之前就检查出这样的错误.
Try…catch对每个catch语句都从头到尾检查,如果找到处理同类异常的catch子句,此catch块中的语句将得以执行,而不再处理同层次的其它catch块.
如果catch或finally抛出另一个异常,程序将不会再去检查try的catch子句.
Try...catch语句可以嵌套,内层抛出的异常可被外层处理.

Throws子句

函数能抛出的检查型异常用throws声明,它后面可以是带用逗号隔开的一系列异常类型.仅仅那些在方法中不被捕获的异常必须列出.

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // Read in any hidden serialization magic
        s.defaultReadObject();

        // Read in size
        int size = s.readInt();

        // Initialize header
        header = new Entry<E>(null, null, null);
        header.next = header.previous = header;

        // Read in all elements in the proper order.
        for (int i=0; i<size; i++)
             addBefore((E)s.readObject(), header);
        }
}

More…

Throws子句的约定是严格强制性的,只能抛出throws子句中声明的异常类型,抛出其它类型的异常是非法的,不管是直接利用throw,还是调用别的方法间接的抛出.
RuntimeException和Error是仅有的不必由throws子句列出的异常.
调用函数的函数要么处理对声明的异常进行处理,要么也声明同样的异常,将收到的异常抛向上层.

对检查型异常通常进行的几种处理
1) 用e.printStackTrace()输出异常信息.
2) 将异常记录到日志中以备查,如logger.error(e.getMessage()).
3) 试图进行异常恢复.
4) 告知维护者和用户发生的情况.

posted on 2008-02-21 20:09 和风细雨 阅读(239) 评论(0)  编辑  收藏 所属分类: J2SE


只有注册用户登录后才能发表评论。


网站导航: