ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
### [历史](https://lingcoder.gitee.io/onjava8/#/book/15-Exceptions?id=%e5%8e%86%e5%8f%b2) 异常处理起源于 PL/1 和 Mesa 之类的系统中,后来又出现在 CLU、Smalltalk、Modula-3、Ada、Eiffel、C++、Python、Java 以及后 Java 语言 Ruby 和 C# 中。Java 的设计和 C++ 很相似,只是 Java 的设计者去掉了一些他们认为 C++设计得不好的东西。 为了能向程序员提供一个他们更愿意使用的错误处理和恢复的框架,异常处理机制很晚才被加入 C++ 标准化过程中,这是由 C++ 的设计者 Bjarne Stroustrup 所倡议。C++ 的异常模型主要借鉴了 CLU 的做法。然而,当时其他语言已经支持异常处理了:包括 Ada、Smalltalk(两者都有异常处理,但是都没有异常说明),以及 Modula-3(它既有异常处理也有异常说明)。 Liskov 和 Snyder 在他们的一篇讨论该主题的独创性论文中指出,用瞬时风格(transient fashion)报告错误的语言(如 C 中)有一个主要缺陷,那就是: > “....每次调用的时候都必须执行条件测试,以确定会产生何种结果。这使程序难以阅读并且有可能降低运行效率,因此程序员们既不愿意指出,也不愿意处理异常。” 因此,异常处理的初衷是要消除这种限制,但是我们又从 Java 的“被检查的异常”中看到了这种代码。他们继续写道: > “....要求程序员把异常处理程序的代码文本附接到会引发异常的调用上,这会降低程序的可读性,使得程序的正常思路被异常处理给破坏了。” C++ 中异常的设计参考了 CLU 方式。Stroustrup 声称其目标是减少恢复错误所需的代码。我想他这话是说给那些通常情况下都不写 C 的错误处理的程序员们听的,因为要把那么多代码放到那么多地方实在不是什么好差事。所以他们写 C 程序的习惯是,忽略所有的错误,然后使用调试器来跟踪错误。这些程序员知道,使用异常就意味着他们要写一些通常不用写的、“多出来的”代码。因此,要把他们拉到“使用错误处理”的正轨上,“多出来的”代码决不能太多。我认为,评价 Java 的“被检查的异常”的时候,这一点是很重要的。 C++ 从 CLU 那里还带来另一种思想:异常说明。这样,就可以用编程的方式在方法签名中声明这个方法将会抛出异常。异常说明有两个目的:一个是“我的代码会产生这种异常,这由你来处理”。另一个是“我的代码忽略了这些异常,这由你来处理”。学习异常处理的机制和语法的时候,我们一直在关注“你来处理”部分,但这里特别值得注意的事实是,我们通常都忽略了异常说明所表达的完整含义。 C++ 的异常说明不属于函数的类型信息。编译时唯一要检查的是异常说明是不是前后一致;比如,如果函数或方法会抛出某些异常,那么它的重载版本或者派生版本也必须抛出同样的异常。与 Java 不同,C++ 不会在编译时进行检查以确定函数或方法是不是真的抛出异常,或者异常说明是不是完整(也就是说,异常说明有没有精确描述所有可能被抛出的异常)。这样的检查只发生在运行期间。如果抛出的异常与异常说明不符,C++ 会调用标准类库的 unexpected() 函数。 值得注意的是,由于使用了模板,C++ 的标准类库实现里根本没有使用异常说明。在 Java 中,对于泛型用于异常说明的方式存在着一些限制。