这通常不是关于异常处理的问题,但它特别适用于某些框架的使用。一些典型起点的例子:
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...
}
}
由于我不是“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...
}
}
我的问题是:在性能,最佳做法,代码可读性,一般安全性或其他任何我不考虑或注意的事项方面是否有任何缺点 - 使用这种方法? < / p>
答案 0 :(得分:4)
使用异常来指导正常环境下的程序流是一种代码味道,但这并不是你在这里所做的。我认为你可以通过以下几个原因来解决这个问题:
我们已经出于各种原因捕获并重新抛出异常(例如,“捕获,采取某些行动,传播”)。这在意图上有点不同,但在成本方面并没有差别。
您已经承担了至少一次抛出此异常的费用。您可能已经承担了抛出,抓住,包裹或重新抛出原因的成本。填写堆栈跟踪的成本已经支付。再一次重新抛出已经填充的异常并不会增加复杂性的顺序。
您没有使用例外来指导普通代码路径的流程。您对错误做出了反应,因此您已经在例外路径上,并且您应该很少(如果有的话)在这里结束。如果这种模式效率低下,除非遇到 lot 异常,否则几乎没有问题,在这种情况下你会遇到更大的问题。花时间优化您期望采取的路径,而不是那些您没有的路径。
在美学上,当条件仅仅是类型检查时,很少有东西会使我的皮肤像if/else if
块的长链一样爬行,尤其是。在我看来,你提出的建议更具可读性。拥有多个有序的catch
子句很常见,因此结构主要是熟悉的。 try { throw e; }
序言可能是非正统的,但很容易理解。
宣传Throwable
时要小心谨慎。一些错误,例如VirtualMachineError
层次结构,表明某些事情已经发生了可怕的错误,应该允许它们运行。其他人,如InterruptedException
,会传达有关原始线程状态的信息,不应在不同的线程上盲目传播。有些内容,如ThreadDeath
,可以跨越两个类别。
答案 1 :(得分:2)
性能只有在抛出大量错误时才有意义。它不会影响成功案例中的表现。有太多的错误比处理它们的时间要多得多。
如果调用本地方法,并抛出异常,那么使用catch块来处理它就没问题了。这是相同的,但使用远程方法。这不是正常的控制流,因为在获取方法之前已经从RPC调用中抛出异常,因此使用通常的异常处理结构是可以的。
编译器可以执行一些检查,例如检查是否首先列出了最具体的异常,但是使用通用Throwable
类型会丢失某些类型的安全性。由于框架,这是不可避免的。
对于这里的任何一个例子我都没问题,因为它没有太大的区别。
答案 2 :(得分:0)
你展示的两个代码块实际上非常相似:乍一看它们与我的眼睛都是相同的“形状”。
值得注意的是if / else链实际上比try / catch版本更少的代码行更容易理解。
我认为try / catch版本本身并不是错误,但是当像这样并排比较时,我没有看到任何理由为什么更好要么。
在其他条件相同的情况下,无争议的代码总是优于有争议的代码:您永远不会希望代码的读者分心,远离 what < / em>您的代码是通过您选择的 来完成的。