回头翻了翻《Java Effective》中的Exception章节(第9章),列几点要点作为笔记:
Java提供了三种Throwable:
checked exceptions: 继承于Exception的异常类 runtime exceptions: 继承于RuntimeException的异常类 errors: 继承于Throwale的异常类这些异常可以被分为两种:
Checked Exception: 对应于上面三种Throwable的第一种;这种异常必须使用try-catch进行处理(即要么把异常处理掉,如记log或者恢复等处理操作;要么把异常抛到上层调用中去)。此外,如果父类的方法声明了throws ExceptionA, ExceptionB...,那么子类重写该方法时,所声明的throws后面的异常类只能是父类声明的子集,不能新增其它异常类,否则编译通不过;在调用这些方法时,如果没有try-catch代码块,编译也通不过。 Unchecked Exception:对应于上面三种Throwable的第二、三种;由于Error一般用于JVM,故编写程序时一般不会使用,所以常用的Unchecked Exception一般指的是RuntimeException及其子类。这种异常不强制使用try-catch,即在调用的过程中可以不使用try-catch代码块;同时父类方法声明中的throws对子类重写方法所写的throws没有限制,甚至声明中可以不用写throws。异常使用的性能:
所有异常类都是Throwable的子类(只有Throwable的子类才能通过Java的thow语句抛出),但使用异常会导致性能变差,根本原因在于Throwable的fillInStackTrace()方法:
public synchronized native Throwable fillInStackTrace()
性能开销在于: 方法是同步的(synchronized),且需要填充线程运行堆栈信息;如果重写该方法、去掉同步就能够使性能大大提高(try...catch和if...else的性能开销在同一数量级,性能优化不大) 性能这点的测试请参见:http://www.blogjava.net/stone2083/archive/2010/07/09/325649.html
常用的RuntimeException(继承于Exception)类
IllegalArgumentException: 调用者传入的参数不合适时使用IllegalStateException: 调用的接收者状态非法(如调用者试图去使用状态未正确初始化对象) 场合一:JSP网页中,session失效后,再使用getXXX()方法就会抛出IllegalStateException场合二:在使用java.util.Iterator的时候,Iterator的remove()方法必须在调用next()方法后调用,且每次next()之后只能调用一次remove(),当Iterator的集合被修改后其状态为unspecified。如果上次访问(next())后集合已被修改,方法将抛出IllegalStateException。 NullPointerException: 如果禁止传入的参数是null时使用IndexOutOfBoundsException: 如果序列的索引参数超出范围时使用ConcurrentModificationException:一个对象设计为用于单线程或者带有外部同步检测时,如果被并发修改了,则会抛该异常UnsupportedOperationException: 对象不支持所发起的操作时抛出该异常 场合一: 一个只支持添加元素的List,如果调用remove(),则抛出该异常场合二: 实际的Iterator如果不支持remove()方法,那么调用时会抛出该异常异常如果不处理,那么可以通过一层一层往上层抛(异常传递);但这种方式不太好的方式,因为这样会使得上层的API与下层的API耦合故当下层的异常要再往上层抛时,需要经过转换为上层的异常后再抛出。转换时,尽量要把下层的信息放到转换后的异常对象中;有两种办法可使得上层异常能够包含下层异常信息,上层异常可使用getCause()方法获取到下层异常:
转换为上层异常时,可把下层异常当作上层异常的构造函数传入转换为上层异常时,使用initCause(Throwable cause)方法把下层异常传入这两种办法不仅仅是使得上层异常能够得到下层异常的信息,它还能下层异常的stack trace集成到上层中。
此外,虽然exception的转换比exception传递更优越,但不应滥用
最好的方式是避免下层产生异常(如对上层参数先进行检测,然后再传入下层)如果异常不可避免,那最好能够让上层把异常处理掉,使得调用者的上层与下层的问题隔离开来 (比如使用log的方式把异常记录下来,以便管理员调查)