《面向对象的思考过程(原书第4版)》一3.2 错误处理

简介: 首次编写一个类时总想让它完美无缺。但在大多数情况下,事情却往往不是我们想象的那样。开发人员不预先处理错误,会将程序置于危险之中。 假如想在代码中加入识别错误和处理错误的能力,有好几种方式。在《Java Primer Plus》(9781571690623?)一书的第223页,Tyma、Torok和Downing指出在程序中有三种基本的解决方案来处理发现的问题:修复问题、通过压制来忽略问题,或以合适的方式退出运行时。

本节书摘来自华章出版社《面向对象的思考过程(原书第4版)》一书中的第3章,第3.2节,[美] 马特·魏斯费尔德(Matt Weisfeld) 著黄博文 译更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.2 错误处理

首次编写一个类时总想让它完美无缺。但在大多数情况下,事情却往往不是我们想象的那样。开发人员不预先处理错误,会将程序置于危险之中。
假如想在代码中加入识别错误和处理错误的能力,有好几种方式。在《Java Primer Plus》(9781571690623?)一书的第223页,Tyma、Torok和Downing指出在程序中有三种基本的解决方案来处理发现的问题:修复问题、通过压制来忽略问题,或以合适的方式退出运行时。《Java面向对象设计》(9781571691347)一书中的第139页,Gilbert和McCarty解释了异常处理的几个选择:
忽略该问题。这不是好主意!?
检查潜在的问题,当发现问题时中止程序。?
检查潜在的问题,捕获错误并试图修复该问题。
抛出异常(通常这是处理异常的最佳方式)?。
下面详细讨论了这些策略。

3.2.1 忽略问题

简单地忽略潜在的问题往往会引发灾难。如果你想忽略该问题,那么为什么不在发现时就处理它?显然,不应该忽略任何已知的问题。所有应用程序的基本职责是保证程序绝不崩溃。如果不处理错误,应用程序最终会以丑陋的方式崩溃掉,或者进入一种不稳定的状态。之后继续使用的话你甚至不知道得到结果是否是正确的,这比程序崩溃更糟糕。

3.2.2 检查问题并中止应用程序

如果检查潜在的问题,并且当检测到问题时中止应用程序,应用程序可以显示一条关于该问题的信息。这种情况下应用程序优雅地退出,但留下用户盯着计算机屏幕,想搞清楚刚才发生了什么。显然,这是一个远胜于忽略问题的选项,但它不是最佳选项。不过这可以让系统收拾残局并进入稍稳定的状态,比如关闭文件和强制系统重启。

3.2.3 检查问题并试图恢复

检查潜在问题,捕获错误,并试图恢复的方案远胜于简单地检查问题并中止程序的方案。在这种情况下,通过代码检测发现问题,然后应用程序自身会尝试修复它。这在某些场景下是适用的。例如,请看以下代码:
d3_1
显然,如果代码中没有该条件语句,0会进入除法语句,因为不能除以0,从而导致系统异常。捕获该异常并设置变量a为1,至少能保证系统不会崩溃。不过设置a为1可能不是一个正确的方案,因为结果是不正确的。更好的方案是提醒用户重新输入恰当的值。
混合错误处理技术
尽管事实上错误处理类型并不属于面向对象的核心范畴,但我认为在面向对象设计中可以考虑使用。抛出异常(接下来的小节会涉及)会带来昂贵的开销。因此,尽管异常是有效的设计决策,你也应该根据设计及性能要求,适当考虑其他错误处理技术(甚至使用tried-and-true结构化技术)。
之前提到的错误检查技术强于什么都不做,但这种技术也有一些问题。比如并不总能在错误第一次发生的地方就能探测到该错误。很可能问题发生一段时间后才会被探测到。不过详细解释异常处理已经超出了本书的范围。然而,一开始设计类时就设计异常处理是非常重要的,而且通常操作系统自身也会对它发现的问题发出警告。

3.2.4 抛出异常

大多数面向对象的语言提供了名为异常的功能。通常来讲,异常是系统内发生的突发事件。异常提供了一种方式来检测问题然后进行处理。在Java、C#、C++、Objective-C和Visual Basic中,异常是通过关键字catch和throw来处理的。这有点像棒球游戏,但这里的关键概念是用特定的代码块用来处理特定的异常。这既解决了尝试找出错误发生的地方的问题,也解决了在正确的地方处理该错误的问题。
以下是Java中try/catch代码块的结构:
d3_2
如果在try代码块中抛出了异常,catch代码块会处理该异常。如果代码块执行过程中抛出了异常,会发生以下事情:
1)try代码块会结束执行。
2)catch从句会检查对应的catch代码块能否处理这种异常。(一个try代码块可能会对应多个catch从句。)
3)如果所有catch代码块都不能处理抛出的异常,那么该异常会传递给最近的更高一层的try代码块中(如果代码中没有捕获该异常,系统最终会捕获它,结果是无法预料的,可能导致应用程序崩溃)。?
4)如果有一个catch从句匹配上了(遇到了第一个匹配的从句),会执行catch从句中的代码。
5)程序会从紧挨着try代码块的下面的代码处恢复执行。
以上几点足够说明异常处理是面向对象程序语言中的一个重要优势。以下是Java中处理异常的一个示例:
d3_3
异常粒度
你可以在不同层级的粒度上捕获异常。你可以捕获所有的异常或者检查特定的异常(比如算术异常)。如果代码没有捕获异常,Java运行时会捕获它,那么Java运行时可能会崩溃!
在以上代码中,try代码块中除以0(因为count等于0)会导致算术异常。如果异常发生(抛出)在try代码块之外,程序很可能会中止(崩溃)。然而,因为异常是在try代码块中抛出的,catch代码块会检查是否能处理特定的异常(本例中即算术异常)。因为catch代码块包含了对算术异常的检查,所以catch代码块中的代码会执行,设置count为1。在catch代码块执行之后,try/catch代码块会退出,并把异常被处理的信息输出到Java终端。图3-5展示了整个处理过程。
3_5
如果没有把ArithmeticException放入catch代码块,程序很可能会崩溃。可以使用以下代码来捕获所有异常:
d3_4
catch块中的Exception参数能够匹配在try代码块中产生的任何异常。
稳定的代码
综合使用以上描述的方式可以保证应用程序尽可能保持稳定的状态。

相关文章
|
25天前
|
程序员 测试技术 数据库连接
PHP编程中的错误处理技巧
在PHP编程中,处理错误是至关重要的一环。本文将介绍几种常见的PHP错误类型及其处理技巧,包括语法错误、运行时错误和逻辑错误。通过学习正确的错误处理方法,可以提高代码的可靠性和可维护性,从而更好地保障程序的稳定性和安全性。
17 2
|
2月前
|
Go 开发者
Go语言中的错误处理与异常机制:实践与最佳策略
【2月更文挑战第7天】Go语言以其独特的错误处理机制而闻名,它鼓励显式错误检查而不是依赖于异常。本文将探讨错误处理与异常机制在Go语言中的实际应用,并分享一些最佳实践,帮助开发者编写更加健壮和易于维护的Go代码。
|
3月前
|
前端开发 JavaScript 安全
Promise/A+ 规范详解:打造健壮异步代码的必备知识(上)
Promise/A+ 规范详解:打造健壮异步代码的必备知识(上)
Promise/A+ 规范详解:打造健壮异步代码的必备知识(上)
|
2月前
|
Go 开发者
Go语言错误处理机制:原理与实践
【2月更文挑战第7天】在Go语言中,错误处理是一项核心特性。Go语言鼓励显式的错误检查,而不是依赖于异常机制。本文将深入探讨Go语言的错误处理机制,包括错误的表示、传播和处理方式,以及如何在日常编程中有效地应用这一机制,确保代码的健壮性和可读性。
34 10
|
3月前
|
前端开发 安全
Promise/A+ 规范详解:打造健壮异步代码的必备知识(下)
Promise/A+ 规范详解:打造健壮异步代码的必备知识(下)
Promise/A+ 规范详解:打造健壮异步代码的必备知识(下)
|
5月前
|
Java UED
异常处理:让你的代码更加健壮
异常处理:让你的代码更加健壮
|
JavaScript
【重温基础】2.流程控制和错误处理
【重温基础】2.流程控制和错误处理
89 0
出错保障局-异常处理机制 | 带你学《Java面向对象编程》之七十六
没有一个开发者的代码是绝对不会出错的,Java为了尽量提前发现错误,推出了异常处理机制。
|
Java 程序员 容器
《领域特定语言》一3.7 错误处理
本节书摘来自华章出版社《领域特定语言》一书中的第3章,第3.7节,作者 (英)Martin Fowler,更多章节内容可以访问云栖社区“华章计算机”公众号查看
855 0