error 和 exception 这两个术语通常用作行话术语,其含义因使用它们的编程生态系统而异。
条件
此响应遵循Common Lisp 的引导,并采用术语条件 作为引用程序中“有趣情况”的非判断方式。
是什么让程序条件“有趣”?让我们考虑实数被零除的情况。在绝大多数情况下,一个实数除以另一个实数,结果是另一个普通的普通的良善实数。这些是“常规”或“无趣”的案例。但是,在除数为零的情况下,从数学上讲,结果是不确定的。该程序现在处于“有趣”或“异常”的状态。
一旦我们采用实数的数学理想并将其建模为IEEE-format floating point number,它就会变得更加复杂。如果我们除以 1.0 / 0.0,IEEE 标准(大部分)说结果实际上是另一个浮点数,安静的 NaN Infinity。由于结果不再像普通的旧实数那样表现,因此程序条件再次“有趣”或“异常”。
分类条件
问题是:当我们遇到有趣的情况时应该怎么做?答案取决于上下文。在对程序条件进行分类时,以下问题很有用:
- 这种情况发生的可能性有多大:确定、可能、不太可能、不可能?
- 如何检测到条件:程序故障、可分辨值、信号/处理程序(又名exception handling)、程序终止?
- 应该如何处理条件:忽略它,执行一些特殊操作,终止程序?
这些问题的答案产生了 4 x 4 x 3 = 48 个不同的案例——当然更多的案例可以通过进一步的标准来区分。这将我们带到了问题的核心。我们有两个以上的案例,但只有两个标签,error 和 exception,可以应用于它们。不用说,有很多可能的方法可以将 48+ 案例分为两组。
例如,可以说任何涉及程序故障的事情都是错误,其他任何事情都是异常。或者任何涉及语言内置exception handling 设施的东西都是异常,其他任何东西都是错误。可能性很多。
示例
文件结束
在读取和处理字符流时,肯定会到达文件末尾。在 C 中,这个事件是通过 I/O 函数的一个可区分的返回值来检测的,即所谓的 error 返回值。因此,有人说 EOF 错误。
除以零
在简单的计算器程序中将两个用户输入的数字相除时,即使用户输入的除数为零,我们也希望给出有意义的结果。在某些 C 环境中,除以零会产生一个 信号 (SIGFPE),该信号必须由信号处理程序处理。信号有时在 C 社区中被称为 exceptions,而令人困惑的是,有时被称为程序 error 信号。在其他 C 环境中,应用 IEEE 浮点规则,除以零将导致 NaN 值。 C 环境会很高兴地不知道该值,认为它既不是异常也不是错误。
运行时加载失败
程序经常在运行时动态加载其程序代码(例如类、DLL)。由于缺少文件,这可能会失败。 C 没有提供检测或从这种情况中恢复的标准方法。程序会不自觉地终止,人们经常将这种情况称为致命的异常。在 Java 中,这将被称为链接错误。
Java 的 Throwable 层次结构
Java 的异常处理系统将所谓的Throwable 类层次结构分为两个主要组。 Error 的子类旨在表示无法恢复的情况。 Exception 的子类用于可恢复的条件,进一步细分为检查异常(用于可能的情况)和未检查的异常(用于不太可能的情况)。不幸的是,这些类别之间的界限定义不明确,您经常会发现其语义表明它们属于不同类别的 throwable 实例。
警惕行话
这些例子表明 error 和 exception 的含义充其量是模糊的。必须将error和exception视为行话,其含义由讨论的上下文决定。
具有更大价值的是程序条件的显着特征。这种情况发生的可能性有多大?病情如何检测?检测到该情况时应采取什么措施?在任何需要清晰的讨论中,更适合直接回答这些问题,而不是依赖行话术语。