用户定义异常:何时使用它们?什么是“异常”情况?

4
我相信很多最佳实践书籍中都已经解决了这个问题,但是大多数情况下我看到的自定义异常使用示例都是错误的,因此我想知道什么情况下使用它们会比较好?
特别是,目前我正在为编译器课程开发类型检查器。因此,我有一个SymbolTable类,它非常类似于Map。与普通映射的主要区别在于每个符号最多只能定义一次,因此如果我们尝试插入的键已经存在于SymbolTable中,则put(String,Object)操作应该失败。
那么问题来了:每当我们尝试插入一个键并且该键已经存在于SymbolTable中时,SymbolTable应该如何行动?我们应该拥有一个
boolean insert(String key, Object value);

在插入失败时返回“false”的方法?还是我们应该使用返回值为“void”的插入方法,在遇到重复值时抛出异常?
提前感谢:)
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);

2
决定使用异常还是返回值需要平衡几个“因素”:
- 调用者可以忽略返回值并继续执行下一行,但不能忽略异常。异常通常在可能导致更大问题的情况下使用。 - 异常会给调用者带来负担,因为处理它们的代码比仅检查返回值要复杂得多。因此,在简单返回值足以满足要求时通常会避免使用异常。 - 另一方面,异常可以让立即调用者免除检查结果的负担,因为它可以相信如果出现问题,堆栈将被展开到其他地方的catch块。 - 异常处理比普通返回更复杂,因此如果它们经常被抛出,就会有性能损失。异常通常用于不经常发生的情况。 - 当错误信息和“正常”结果具有不同的类型时,抛出异常通常比将无关的事物塞入相同的返回值中更好(例如使方法返回Object,以便它可以返回字符串或数字)。
在符号表的示例中,我可能只会返回false,因为这很可能会使代码更简单,但是根据程序的设计,任何一种方式都是合理的。

0
User defined exceptions: when do we use them?

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


0

这真的取决于你认为会发生什么。以你的插入示例为例,是否预期存在重复项,或者存在重复项是否不正常?如果情况是异常的(即通常不应该发生的事情),那么就是异常情况。

你不应该使用异常来控制流程。如果说有10%的时间预计会出现重复项,那么使用异常将是无效的。但如果程序员犯了错误(即在不应该放置重复项时放置了重复项),那么也许异常是适当的。

虽然这个问题已经被讨论过很多次了,不过还是可以再搜索一下。


理想情况下,如果编译的程序是正确的,就不会有重复插入的情况。但是根据我的编程经验,能够成功编译的程序往往是少数而非多数 :) - Emil D
在这种情况下,异常非常适合您的用例,特别是在 Java 中,异常似乎被广泛接受。抛出异常使您处理错误而不是忽略它。 - jli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接