-
对 Checked Exceptions 特性持保留态度
(译者注:在写一段程序时,如果没有用 try-catch 捕捉异常或者显式的抛出异常,而希望程序自动抛出,一些语言的编译器不会允许编译通过,如 Java 就是这样。这就是 Checked Exceptions 最基本的意思。该特性的目的是保证程序的安全性和健壮性。 Zee&Snakey(MVP) 对此有一段很形象的话,可以参见: http : //www.blogcn.com/user2/zee/main.asp 。 Bruce Eckel 也有相关的一篇文章(《 Does Java need Checked Exceptions 》),参见: http : //www.mindview.net/Etc/Discussions/CheckedExceptions )
Bruce Eckel : C# 没有 Checked Exceptions ,你是怎么决定是否在 C# 中放置这种特性的么?
Anders Hejlsberg :我发现 Checked Exceptions 在两个方面有比较大的问题:扩展性和版本控制。我知道你也写了一些关于 Checked Exceptions 的东西,并且倾向于我们对这个问题的看法。
Bruce Eckel :我一直认为 Checked Exceptions 是非常重要的。
Anders Hejlsberg :是的,老实说,它看起来的确相当重要,这个观点并没有错。我也十分赞许 Checked Exceptions 特性的美妙。但它某些方面的实现会带来一些问题。例如,从 Java 中 Checked Exceptions 的实现途径来看,我认为它在解决一系列既有问题的同时,付出了带来一系列新问题的代价。这样一来,我就搞不清楚 Checked Exceptions 特性是否可以真的让我们的生活变得更美妙一些。对此你或许有不同看法。
Bruce Eckel : C# 设计小组对 Checked Exceptions 特性是否有过大量的争论?
Anders Hejlsberg :不,在这个问题上,我们有着广泛的共识。 C# 目前在 Checked Exceptions 上是保持缄默的。一旦有公认的更好的解决方案,我们会重新考虑,并在适当的地方采用的。我有一个人生信条,那就是——如果你对该问题不具有发言权,也没办法推进其解决进程,那么最好保持沉默和中立,而不应该摆出一个非此即彼的架势。
假 设你让一个新手去编一个日历控件,他们通常会这样想:“哦,我会写出世界上最好的日历控件!我要让它有各种各样的日历外观。它有显示部分,有这个,有那 个……”他们将所有这些构想都放到控件中去,然后花两天时间写了一个很蹩脚的日历程序。他们想:“在程序的下一个版本中,我将实现更多更好的功能。”
但 是,一旦他们开始考虑如何将脑海中那么多抽象的念头具体实现出来时,就会发现他们原来的设计是完全错误的。现在,他们正蹲在一个角落里痛苦万状呢,他们发 现必须将原来的设计全盘抛弃。这种情况我不是看到一次两次了。我是一个最低纲领主义者。对于影响全局的问题,在没有实际解决方案前,千万不要将它带入到整 个框架中去,否则你将不知道这个框架在将来会变成什么样子 。
Bruce Eckel :极限编程(The Extreme Programmers)上说:“用最简单的办法来完成工作。”
Anders Hejlsberg :对呀,爱因斯坦也说过:“尽可能简单行事。”对于Checked Excpetions特性,我最关心的是它可能给程序员带来哪些问题。试想一下,当程序员调用一些新编写的有自己特定的异常抛出句法的API时,程序将变 得多么纷乱和冗长。这时候你会明白Checked Exceptions不是在帮助程序员,反而是在添麻烦。正确的做法是,API的设计者告诉你如何去处理异常而不是让你自己想破脑袋。
-
Checked Exceptions的版本相关性
Bill Venners :你提到过 Checked Exceptions的扩展性和版本相关性这两个问题。现在能具体解释一下它们的意思么?
Anders Hejlsberg :让我首先谈谈版本相关性,这个问题更容易理解。假设我创建了一个方法 foo ,并声明它可能抛出 A 、 B 、 C 三个异常。在新版的 foo 中,我要增加一些功能,由此可能需要抛出异常 D 。这将产生了一个极具破坏性的改变,因为原来调用此方法时几乎不可能处理过 D 异常。
也就是说,在新版本中增加抛出的异常时,给用户的代码带来了破坏。在接口中使用方法时也有类似的问题。一个实现特定功能的接口一经发布,就是不可改变的,新功能只能在新版的接口中增加。换句话说,就是只能创建新的接口。在新版本中,你只有两种选择,要么建立一个新的方法 foo2 , foo2 可以抛出更多的异常,要么在新的 foo 中捕获异常 D ,并转化为原来的异常 A 、 B 或者 C 。
Bill Venners :但即使在没有 Checked Exceptions特性的语言中,(增加新的异常)不是同样会对程序造成破坏么?假如新版foo抛出了需要用户处理的新的异常,难道仅仅因为用户不希望这个异常发生,他写代码时就可以置之不理吗?
Anders Hejlsberg :不,因为在很多情况下,用户根本就不关心(异常)。他们不会处理任何异常。其实消息循环中存在一个最终的异常处理者,它会显示一个对话框提示你程序运行出错。程序员在任何地方都可以使用 try finally 来保护自己的代码,即使运行时发生了异常,程序依然可以正确运行。对于异常本身的处理,事实上,程序员是不关心的。
很多语言的 throws 语法(如 Java ),没必要地强迫你去处理异常,也就是逼迫你搞清楚每一个异常的来源。它们要求你要么捕获声明的异常,要么将它们放入 throws 语句。程序员为了达到这个要求,做了很多荒谬可笑的事情。例如他们在声明每个方法时,都必须加上修饰语:“ throws Exception ”。这完全是在搧这个特性的耳光,它不过是要求程序员多作些官样文章,对谁都没有好处。
Bill Venners :如此说来,你认为不要求程序员明确的处理每个异常的做法,在现实中要适用得多了?
Anders Hejlsberg :人们为什么认为(显式的)异常处理非常重要呢?这太可笑了。它根本就不重要。在我印象中,一个写得非常好的程序里, try finally 和 try catch 语句数目大概是 10 : 1 。在 C# 中,也可以使用和类似 try finally 的 using 语句(来处理异常)。
Bill Venners : finally 到底干了些什么?
Anders Hejlsberg : finally 保 证你不被异常干扰,但它不直接处理异常。异常处理应该放在别的什么地方。实际上,在任何一个事件驱动的(如现代图形界面)程序中,在主消息循环里,都有一 个缺省的异常处理过程,程序员只需要处理那些没被缺省处理的异常。但你必须确保任何异常情况下,原来分配的资源都能被销毁。这样一来,你的程序就是可持续 运行的。你肯定不希望写程序时,在 100 个地方都要处理异常并弹出对话框吧。如果那样的话,你作修改时就要倒大霉了。异常应该集中处理,并在异常来临处保护好你的代码。
-
Checked Exceptions 的扩展性
Bill Venners :那么 Checked Exceptions 的扩展性又是如何呢?
Anders Hejlsberg : 扩展性有时候和版本性是相关的。 在一个小程序里, Checked Exceptions 显得蛮迷人的。你可以捕捉 FileNotFoundException 异常并显示出来,是不是很有趣?这在调用单个的 API 时也挺美妙的。但是在开发大系统时,灾难就降临了。你计划包含 4 、 5 个子系统,每个子系统抛出 4 到 10 个异常。但是(实际开发时),你每在系统集成的梯子上爬一级,必须被处理的新异常都将呈指数增长。最后,可能每个子系统需要抛出 40 个异常。将两个子系统集成时,你将必须写 80 个 throw 语句。最后,可能你都无法控制了。
很多时候, Checked Exceptions 都会激怒程序员,于是程序员就想办法绕过这个特性。他要么在到处都是写“ throws Exception ”,要么——我都不知道自己看到多少回了——写“ try, da da da da da( 译者注:意思是飞快的写一段代码 ), catch curly curly( 译者注:即‘ { } ’ ) ”,然后说:“哦,我会回头来处理这些空的异常处理语句的。”实际上,理所当然的没有任何人会回头干这些事情。这时候, Checked Exceptions 已经造成系统质量的极大下降。
所以,你可能很重视这些问题,但是在我们决定是否将 Checked Exceptions 的一些机制放入 C# 时, 却是颇费了一番思量的。当然,知道什么异常可能在程序中抛出还是有相当价值的,有一些工具也可以作这方面的检查。我不认为我们可以建立一套足够严格而严谨 的规则(来完成异常检查),因为(异常)还可能是编译器的错误引起的呢。但是我认为可以在(程序)分析工具上下些功夫,检测是否有可疑代码,是否有未捕获 的异常,并将这些隐藏的漏洞给你指出来。
相关推荐
"关于异常的作业"这一主题,通常涉及到如何有效地捕获、处理和预防程序运行时可能出现的错误情况。在这个作业中,我们将深入探讨异常的概念、异常处理机制以及在不同编程语言中的实现方式。 异常是在程序执行过程中...
关于异常的使用心得_1
在机器学习领域,异常检测是一种重要的技术,常用于识别数据中的异常值或离群点。这个数据集专门针对异常检测,对于理解机器学习算法在处理此类问题时的应用具有很高的价值。异常检测通常应用于金融欺诈检测、网络...
通过这个"关于Java异常的练习",你可以实践如何有效地处理异常,理解何时使用不同的关键字,以及如何编写符合最佳实践的异常处理代码。通过对`demo9`等示例代码的分析和修改,加深对Java异常处理机制的理解,提升...
异常通常通过异常类的对象来表示,这些对象包含了关于异常的详细信息。例如,数组下标越界、内存不足、磁盘访问错误或网络访问错误等都可以引发异常。当异常发生时,程序会创建一个异常对象并将其传递给Java运行时...
EXCEPTION_RECORD结构包含了关于异常的所有信息,包括异常代码、异常地址等;而CONTEXT结构则保存了处理器的状态信息,如寄存器的值等。在处理线程异常时,这两个结构通常会被用来获取和分析异常发生时的详细情况,...
Java中的异常处理是编程中非常重要的一个环节,它允许开发者优雅地处理程序中出现的错误,防止程序因未预期的问题而崩溃。异常是程序在运行时遇到的错误,比如除0溢出、数组越界、文件找不到等。Java提供了一整套...
在Java编程语言中,异常处理是一项至关重要的技能,尤其对于初学者来说,理解并熟练掌握异常处理机制是构建健壮程序的基础。Java异常处理的主要目的是中断正常的代码流程,处理程序运行时可能出现的问题,如文件未...
最后,关于异常的继承,Java规定如果子类方法覆盖了父类的方法,那么它可以声明抛出父类方法所声明的异常的子类,但不允许声明抛出比父类方法声明的异常更严格的异常。如果父类方法没有声明抛出任何异常,则子类方法...
代码用于测试c++在文件处理部分的异常操作,同时也对用户输入数据的时候就行了判断,在用户输入性别的时候进行了判断,由于时间问题就没有更多的进行判断。在这里使用到了类的相关功能,同时也做到了保证每次写入...
另一个是描述符,包含了关于异常的一些额外信息,如优先级、处理权限等。 4. **编程接口**:在编程中,我们需要使用特定的API或汇编指令来设置和修改异常向量表。例如,在x86系统中,可以使用`lidt`指令加载中断...
5. **异常链**:Java允许创建异常链,这样就可以保留关于异常起源的完整信息。一个异常可以引用导致它的另一个异常。 6. **多catch块**:Java 7引入了多catch语句,允许在一个catch块中处理多种类型的异常,提高了...
在编程世界中,异常处理是一种重要的错误处理机制,它允许程序在出现异常情况时优雅地进行恢复,而不是突然崩溃。C语言和C++都提供了异常处理功能,但它们的实现方式和理念有所不同。 C语言的异常处理主要是通过...
一些研究者,如Aggarwal等人,提供了广泛的关于异常检测技术的概述。这些技术包括但不限于基于统计的方法、机器学习方法、聚类方法、密度方法和基于邻近度的方法等。 综上所述,时序数据异常检测是一个跨学科的领域...
在Java编程中,异常处理是一项至关重要的技术,它确保了程序在遇到错误或异常情况时仍能保持稳定性和可靠性。异常是在程序编译或运行时出现的错误,这些错误可能会中断程序的正常流程。Java提供了丰富的异常处理机制...
异常确定系统是信息技术领域中的一个重要概念,主要用于检测和识别数据流、系统行为或网络通信中的不寻常模式。这种系统能够帮助我们发现潜在的问题,比如网络安全威胁、设备故障、欺诈行为或者业务过程中的异常情况...
自定义异常通常继承自`Exception`类或其子类,并且可以覆盖构造方法来传递更多关于异常的信息。 #### 六、异常处理示例 下面通过一个简单的示例来展示如何使用异常处理机制: ```java public static void main...
我们描述了复合希格斯模型的异常结构,其中最小模型的SO(5)/ SO(4)陪集结构由一个额外的,非线性实现的U(1)α扩展。 另外,我们表明有效的拉格朗日方程式允许一个术语,如QCD的手性拉格朗日方程中的Wess–“ ...
异常信号隐蔽性高,分析难度大,使得无数工程师都败倒在她的石榴裙下,但因其在信号的分析与调试过程中影响很大,工程师们不得不屡败屡战,一路坎坷前行。本文将结合实例进行分析,分享了一种新颖而实用的异常信号...
- **编码规范**: 关于异常处理的编码规范。 #### 17. C++异常和Visual C++ SEH的混合使用 讨论了如何在C++程序中混合使用标准异常处理和SEH。 - **混合使用**: 如何在C++程序中同时使用C++异常处理和SEH。 - **...