什么时候可以对业务逻辑使用异常处理?

Mic*_*wan 30 java coding-style exception-handling

我认为可以接受的是,作为Java中的一般规则(也许是任何具有异常处理的语言),应该尽量避免使用异常处理来实际处理业务逻辑.一般来说,如果预计会发生某种情况,那么应该检查它并直接处理它,而不是依赖于异常处理来为您进行检查.例如,以下不被视为良好做法:

try{
  _map.put(myKey, myValue);
} catch(NullPointerException e){
  _map = new HashMap<String, String>();
}
Run Code Online (Sandbox Code Playgroud)

相反,懒惰初始化应该更像这样:

if(_map == null){
  _map = new HashMap<String, String>();
}
_map.put(myKey, myValue);
Run Code Online (Sandbox Code Playgroud)

当然,可能存在比简单处理延迟初始化更复杂的逻辑.因此,鉴于此类事情通常不受欢迎......如果有的话,依靠发生某种业务逻辑的异常是一个好主意吗?是否准确地说任何一个人感到被迫使用这种方法的实例是否真的突出了所使用的API的弱点?

a C*_*CVn 32

每当异常可以预期但不能避免时.

比方说,如果你依靠某种外部API来解析数据,那API提供了解析方法,但没有什么可以判断是否可以解析给定的输入(或者解析是否成功取决于因素)您的控件,但API不提供适当的函数调用),并且解析方法在无法解析输入时抛出异常.

使用设计合理的API,这应该可以归结为"几乎从不"到"从不"范围内的某个数量.

我完全没有理由将异常处理用作代码中正常流控制的方法.它很昂贵,很难阅读(只看你自己的第一个例子;我意识到它可能写得很快,但是当_map没有初始化时,你最终得到的是一张空地图,扔掉你正在尝试的条目添加),它使用大量无用的try-catch块来填充代码,这可以很好地隐藏真正的问题.再次以自己的例子,如果调用什么_map.add()都扔NullPointerException出于某种原因其他_mapnull?突然间,您正在静默地重新创建一个空地图,而不是添加一个条目.我确信我不必说,由于意外的状态,可能导致代码中完全不相关的地方出现任意数量的错误......

编辑:为了清楚起见,上面的答案是在Java的上下文中编写的.其他语言可能(并且显然,确实)在异常的实现费用方面有所不同,但其他方面仍应保持不变.

  • Python是一个反对这个问题的有趣例子; 请参阅[维基百科](http://en.wikipedia.org/)上的讨论[此处](http://stackoverflow.com/questions/3086806/python-exceptions-eafp-and-what-is-really-exceptional) wiki/Python_syntax_and_semantics #Exceptions),以及[python.net](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#eafp-vs-lbyl). (2认同)

Ern*_*ill 11

抛出异常是C++中相对昂贵的操作,而且在Java中是非常昂贵的操作.仅从效率的角度来看,避免明确检查并接受异常是没有意义的.我想你也许可以证明它在检查将抛出一个异常是很复杂的或几乎不可能某些罕见的情况下,但除此之外,我想说的答案是"几乎从来没有."

  • 相对于空检查,我会调用fillInStackTrace()非常昂贵.投掷也不那么便宜; 虽然它不涉及在C++中调用析构函数,但它确实涉及通过内部数据结构进行生根,以在堆栈的每个级别找到适当的处理程序. (2认同)