0%

Effective Java 第三版 (9) 异常

异常

§ 只针对异常情况使用异常

拙劣的代码:

1
2
3
4
5
6
7
8
try {
int i = 0;
while (true) {
range[i++].climb();
}
} catch (ArrayIndexOutOfBoundsException e) {

}

该代码使用异常来进行跳出循环。

实际上基于异常的模式比标准模式要慢的多。异常应该只用于异常的情况下,他们永远不应该用于正常的程序控制流程。

§ 对可恢复的情况使用受检异常,对编程错误使用运行异常

三种可抛出的结构:

受检的异常(checked exception)
运行时异常(run-time exception)
错误(error)

§ 避免不必要的使用受检异常

§ 优先使用标准的异常

  • IllegalArgumentException 当传递的参数值不合适的时候,往往会抛出这个异常
  • IllegalStateException 因为接收对象的状态而使调用非法,通常会抛出这个异常
  • NullPointerException 空异常
  • IndexOutOfBoundsException 越界异常
  • ConcurrentModificationException检测专门用于单线程的对象,被并发的修改(这只是提示,因为不可能可靠的监测到并发的修改)
  • UnsupportedOperationException 对象不支持所请求的操作

不要直接重用 ExceptionRuntimeExceptionThrowable 或者 Error

在条件允许的情况下,其他异常也可以被重用,如:ArithmeticExceptionNumberFormatException

§ 抛出与抽象对应的异常

§ 每个方法抛出的异常都需要创建文档

§ 在细节消息中包含失败-捕获信息

§ 保持失败的原子性

一般而言,失败的方法调用应该使对象保持在被调用之前的状态。 如下所示,对 size 进行参数检查,使得对象状态被改变之前,先抛出适当的异常。

1
2
3
4
5
6
7
8
9
10
public Object pop() { 
if (size == 0)
throw new EmptyStackException();

Object result = elements[--size];
elements[size] = null;

/* Eliminate obsolete reference */
return(result);
}

§ 不要忽略异常