异常只应该使用在异常情况下,它们永远不应该用于正常的控制流中.对API设计的启发.
设计良好的API不应该强迫它的客户端为了正常控制流而使用异常.
如果类具有”状态相关”的方法,即只有特定的不可预知的条件下才可以被调用的方法.那么这个类一般具有单独”状态测试”的方法,即指示是否可以调用这个状态的方法.
比如Iterator接口有状态相关的next方法,和对应状态的hasNext方法.可以利用传统的for循环进行标准迭代.
for (Iterator
iter = collection.interator();iter.hasNext();){
Foo foo =iter.next();
//……
}
如果没有hasNext方法,那么客户端被迫使用下面做法:
try {
Iterator
iter = collection.interator()
while (true){
Foo foo = iter.next();
}
} catch (NoSuchElementsException e) {
}
代码繁琐,可读性差,执行效率比标准模式更差,掩盖系统中不相关的bug.
另一种提供单独状态测试的做法是,如果”状态相关”的方法被调用,该对象处于不恰当的状态中,就会返回一个可识别的值,比如null.
对于”状态测试方法”和”可识别的返回值”两种做法,那么什么时候使用呢?
如果对象在缺少外部同步的情况下被并发访问,或者被外界改变状态,使用可识别的方回执很有必要.因为在调用”状态调试”方法和调用对应的”状态相关”方法的时间间隔中,对象的状态可能会发生变化.
如果单独的”状态测试”方法必须充分”状态相关”方法的工作,从性能角度考虑,应该使用可是被的返回值.
如果其他方面等同,那么”状态测试”优先于可识别的返回值,因为它提供更好的可读性;对于不恰当的情景,更加易于检测和更正.
如果忘记调用状态测试方法,状态相关方法会抛出异常,bug明显;如果忘了去检查可识别返回值,bug很难发现.