4

我确信这个问题已经在许多最佳实践书籍中得到解决,但仍然......大多数时候我看到错误使用自定义异常的示例,因此我想知道使用它们的好情况是什么?

特别是,目前我正在为编译器课程开发类型检查器。因此,我有一个 SymbolTable 类,它与 Map 非常相似。与普通地图的主要区别在于必须定义每个符号最多一次,因此如果我们尝试插入的键已经存在于 SymbolTable 中,那么 put(String, Object) 操作应该会失败。

那么问题来了:每当我们尝试插入一个键,而该键已经存在于 SymbolTable 中时,SymbolTable 应该如何表现?我们应该有一个

boolean insert(String key, Object value);

在插入失败时返回“false”的方法?或者我们应该使用具有返回值“void”并在遇到重复值时抛出异常的插入方法?

提前致谢:)

4

4 回答 4

3

异常情况应该抛出异常

在那种特殊情况下,例如,如果方法被命名,insert()我会将已经在列表中的键视为正常情况并更新它。

此外,尽管不应使用异常来控制代码流,但返回布尔值表示失败/成功也不是更好的选择(失败的情况可能很多,而 False 表示没有任何意义)。

最重要的是,我会做一些事情:

// Failures can happen 
void add(key, value) throws AlreadyOnMapException

// Update if already on list
void insert(key, value);

// Make available Contains() methods to control the flow by avoiding exceptions
boolean containsKey(key);

boolean containsValue(value);
于 2011-11-01T04:13:31.010 回答
2

决定使用异常还是返回值是几个“力量”的平衡:

  • 调用者可以忽略返回值并继续下一行,但不能忽略异常。在忽略问题并继续可能导致更大问题的情况下,往往会使用例外。
  • 异常给调用者带来了负担,因为处理它们的代码比仅仅检查返回值更复杂。因此,当一个简单的返回值就足够时,它们通常会被避免。
  • 另一方面,异常可以减轻直接调用者检查结果的负担,因为它可以相信如果出现问题,堆栈将被解开到catch其他地方的块中。
  • 异常处理比普通的返回更复杂,所以如果它们被频繁抛出,就会影响性能。异常通常用于预计不会经常发生的情况。
  • 当错误信息和“正常”结果的类型不同时,抛出异常通常比将不相关的东西硬塞到相同的返回值中更好(例如,让方法返回Object以便它可以返回字符串或数字)。

在您的符号表示例中,我可能只返回 false ,因为它可能会使代码更简单,但两者都可能是合理的,具体取决于程序其余部分的设计。

于 2011-11-01T04:11:59.560 回答
0

这实际上取决于您决定预期会发生什么。使用您的插入示例,是否预期存在重复,或者存在重复是否异常?如果情况不正常(即通常不应该发生的事情),那么它就是异常的。

您不应该做的是使用异常进行流量控制。如果假设有 10% 的时间会出现重复,那么使用异常将是无效的。但是,如果在不应该放入副本的情况下放入副本是程序员的错误(即意外操作),那么可能是一个例外。

这已经被讨论死了,试着搜索一下。

于 2011-11-01T04:03:39.827 回答
0
User defined exceptions: when do we use them?

我确信在许多书中都有非常明确的场景可以使用基于自定义的异常。然而最近我观察到一个有趣的使用基于自定义的异常,即改进日志记录。例如A类函数调用B类函数,B类函数调用C类函数,所有这些函数都可以抛出IO异常。因此,如果 IO 异常出现在 C 类函数中,则捕获该异常,记录它,现在制作基于自定义异常的对象并抛出该对象。每个调用函数都会捕获基于自定义的异常以及其他异常,并且每当他们捕获基于自定义的异常时,他们不会记录它,因为这将是多余的,他们只是将其扔回去。

于 2011-11-01T04:12:04.867 回答