Lou*_*ono 7 java exception-handling
这通常不是关于异常处理的问题,但它特别适用于某些框架的使用.典型起点的几个例子:
public void onFailure(Throwable caught)实现AsyncCallback.public Response toResponse(E throwable)实现ExceptionMapper<E extends Throwable>.上述两种方法都接收一个实例Throwable.通常,我看到开发人员使用一个简单的"if/else if"块来区分处理逻辑:
// As specified by the AsyncCallback class of the GWT framework
public void onFailure(Throwable caught) {
if (caught instanceof AnException) {
// handle AnException
} else if (caught instanceof AnotherException) {
// handle AnotherException
} else if (caught instanceof YetAnotherException) {
// handle YetAnotherException
} else if (caught instanceof ...) {
// and so on...
}
}
Run Code Online (Sandbox Code Playgroud)
由于我不是"if/else if"块的粉丝,出于多种原因,我想出了以下"模式",它将"if/else if"块转换为"try/catch"块,表现得好像它是一个"开关"块:
public void onFailure(Throwable caught) {
try {
throw caught;
} catch(AnException e1) {
// handle AnException
} catch(AnotherException e2) {
// handle AnotherException
} catch(YetAnotherException e3) {
// handle YetAnotherException
} catch(...) {
// and so on...
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:是否有任何缺点 - 在性能,最佳实践,代码可读性,一般安全性,或者我没有考虑或注意到的任何其他方面 - 使用这种方法?
在正常情况下使用异常来引导程序流程是一种代码味道,但这并不是您在这里所做的。我认为您可以摆脱这种情况,原因如下:
我们已经出于各种原因捕获并重新抛出异常(例如,“捕获、采取一些操作、传播”)。这在意图上有点不同,但就成本而言并不差。
您已经承担了至少抛出一次此异常的成本。您可能已经承担了其原因被抛出、捕获、包裹或重新抛出的成本。填充堆栈跟踪的成本已经支付。再次重新抛出已经填充的异常不会增加复杂性。
您没有使用异常来引导正常代码路径的流程。您正在对错误做出反应,因此您已经走在了特殊的道路上,并且您应该很少(如果有的话)最终到达这里。如果这种模式效率低下,那么除非您遇到大量异常,否则它几乎没有什么关系,在这种情况下您会遇到更大的问题。花时间优化您期望采用的路径,而不是优化您不采用的路径。
从美学角度来看,没有什么东西像长长的if/else if块链一样让我起鸡皮疙瘩,尤其是当条件仅仅是类型检查时。在我看来,您提出的建议更具可读性。具有多个有序catch子句很常见,因此结构大多是熟悉的。序言try { throw e; }可能不太正统,但很容易推理。
只是传播时要小心Throwable。有些错误,比如VirtualMachineError层次结构,是出现严重错误的迹象,应该允许它们顺其自然。其他的,例如,传达有关原始InterruptedException线程状态的信息,并且它们不应该在不同的线程上盲目传播。有些,例如,跨越这两个类别。ThreadDeath
| 归档时间: |
|
| 查看次数: |
979 次 |
| 最近记录: |