Java:如何处理异常
版权声明:原创作品,如需转载,请与作者联系。否则将追究法律责任。 | ||||||||
在处理异常时,应该区分checked异常和unchecked异常。对于checked异常,我们应该提供健壮的异常恢复机制,而对于unchecked异常,这就是编程错误即bug,应该在调试阶段很好的发现和处理它们。
1. Java异常层次结构
![]() 上图(注:该图引自http://dev2dev.bea.com.cn/techdoc/200702364792.html)标出了Java异常层次结构,也指出了哪些异常是unchecked,哪些异常是checked。下面给出几段常见的异常处理代理,试图总结日常开发中应该如何处理异常。
2.针对checked异常的恢复机制
checked异常并不是编程错误,它的出现是软件运行阶段所不可避免的。最常见的这类异常如socket连接超时。
对于此类异常,我们应该在程序的运行态下试图从异常中恢复过来。下面这段代码(Recover.java)的主要逻辑是,对目标值protected int current进行判断,如果该值大于2则成功,否则抛出NotBigEnoughException异常。
在执行程序的过程中,在每次catch到NotBigEnoughException异常时,我们对current值递增,试图从异常中恢复过来。
NotBigEnoughException.java
Recover.java
结果:
com.zj.exception.types.NotBigEnoughException: reject 0
com.zj.exception.types.NotBigEnoughException: reject 1
com.zj.exception.types.NotBigEnoughException: reject 2
accept 3
3.继承异常
在子类继承父类的情况下,子类override方法的异常声明只能取自(小于等于)父类该方法的异常声明;对于子类构造方法的异常声明必须包含(大于等于)父类构造方法的异常声明。
类Inheritor继承自类Recover,它的方法passing()试图声明一个父类没有的异常UnknowException,这样做是不允许的。
UnknowException.java
error in: Inheritor.java
之所以覆盖这个方法的目的是对父类的passing()方法做进一步扩展,对0<=current<=2的情况抛出NotBigEnoughException,而对current<0的情况则抛出一个新的异常UnknowException。
此时,提供两种解决方法。
方法一,使用恢复异常机制,overrding passing()方法,这样可以处理掉所有的异常,因此不需要异常声明。
ok in: Inheritor.java
方法二,写一个加强的passing()方法,即fortifiedPassing(),对于在父类passing()中捕获的异常,进行再判断。如果是0<=current<=2的情况则重新抛出NotBigEnoughException,如果是current<0的情况则抛出一个新的异常UnknowException。
ok in: Inheritor.java
Inheritor.java
结果:
accept 3
accept 3
accept 3
accept 3
com.zj.exception.types.UnknowException: i don't know how to deal with -1
com.zj.exception.types.NotBigEnoughException: reject 1
at
com.zj.exception.Recover.passing(Recover.java:28)
at
com.zj.exception.Inheritor.fortifiedPassing(Inheritor.java:38)
at
com.zj.exception.Inheritor.main(Inheritor.java:63)
4.RuntimeException与包装异常
RuntimeException是unhecked异常,它们由JVM抛出(你也可以抛出它),并且不必在异常声明(throws)中列出。
如果RuntimeException没有被catch而到达mian()方法时,那么在程序退出前会自动调用该异常的printStackTrace()方法,打印该异常。
RuntimeException代表的是编程错误(如0除数,数组越界),是应该在调试阶段解决的。
当你在捕获某些异常,而不知道该如果处理时,你可以将它包装为RuntimeException,这样在后续的方法调用过程中就不用声明(throws)该方法了。
在类Wrapper中,我们override fortifiedPassing()方法,并将它可能抛出的异常包装为RuntimeException。
Wrapper.java
|



