1. 异常应该只用于异常的情况下,不要将它们用于普通的控制流
- 不要乱用try-catch代码块,当真正需要的时候才使用。例如调用一个方法A,方法A会抛出一个XXXException,这个时候如果需要捕获这个异常来进行一些处理,那么就调用方法A放到try-catch块中。
- 不要使用try-catch代码块来忽略异常。例如方法A会抛出异常,但是为了代码能正常运行,使用try-catch代码块捕获,然后忽略掉异常。如果确实是有这种场景诉求,那么一定要记录好日志。
2. 设计良好的API不应该强迫它的客户端为了正常的控制流而使用异常
我们设计的API,尽量简化客户端的使用,不能让客户端使用我们的API时要做不合理的校验(参考:返回零长度的数组或者集合,而不是null),也不能让客户端做不合理的异常控制(参考如下)。
先理解两个概念:
- “状态相关”(state-dependent)的方法:只有在特定的不可预知的条件下才可以被调用的方法,例如
Iterator#next
方法 - “状态测试”(state-testing)方法:指示是否可以调用这个状态相关的方法,例如
Iterator#hasNext
方法
例如,假设Iterator类没有hasNext方法,那么我们在使用 Iterator#next
方法时,就不知道是否有正常的返回值,这个时候为了正常的代码流程就会加异常处理,例如,客户端调用就会变成这样,这是不合理的:
try {
Iterator<Foo> i = collection.iterator();
while (true){
Foo foo = i.next();
...
}
} catch (NoSuchElementException e){
...
}
API设计者提供了“状态相关”的next方法后,又提供了相应的状态测试方法hasNext,这就简化了客户端的使用,例如:
for (Iterator<Foo> i = collection.iterator(); i.hasNext(); ) {
Foo foo = i.next();
...
}