第七十条:对可恢复的情况使用受检异常,对编程错误使用运行时异常

Java程序设计语言提供了三种可抛出结构:受检异常运行时异常错误。关于什么时候适合使用哪些可抛出结构,程序员中间存在一些困惑。虽然这项决定并不总是那么清晰,但还是有些一般性的原则提出了强有力的指导。

在决定使用受检异常或是未受检异常时,主要的原则是:如果期望调用者能够适当的恢复,对于这种情况就应该使用受检异常。通过抛出受检的异常,强迫调用者在一个catch子句中处理该异常,或者将它传播出去。因此,方法中声明要抛出的每个受检异常,都是对API用户的一种潜在指示:与异常相关联的条件是调用这个方法的一种可能的结果

API的设计者让API用户面对受检异常,以此强制用户从这个异常条件中恢复。用户可以忽视这样的强制要求,只需要捕获异常并忽略即可,但这往往不是好办法(详见第77条)。

有两种未受检的可抛出结构:运行时异常和错误。在行为上两者是等同的:它们都是不需要也不应该被捕获的可抛出结构。如果程序抛出未受检的异常或错误,往往就是属于不可恢复的情形,继续执行下去有害无益。如果程序没有捕捉到这样的可抛出结构,将会导致当前线程中端,并出现适当的错误消息

用运行时异常来表明编程错误。大多数的运行时异常都表示前提违例。所谓前提违例是指API的客户没有遵守API规范建立的约定。例如,数组访问的约定指明了数组的下标值必须在零和数组长度减1之间。ArrayIndexOutOfBoundsException表明违反了这个前提。

这条建议有一个问题:对于要处理可恢复的条件,还是处理编程错误,情况并非总是那么黑白分明。例如,考虑资源枯竭的情形,这可能是由于程序错误引起的,比如分配了一块不合理的过大的数组,也可能确实是由于资源不足而引起的。如果资源枯竭是由于临时的短缺,或是临时需求太大所造成的,这种情况可能就是可恢复的。API设计者需要判断这样的资源枯竭是否允许恢复。如果你相信一种情况可能允许恢复,就使用受检的异常;如果不是,则使用运行时异常。如果不清楚是否可能恢复,最好使用未受检的异常,原因请参考第71条的讨论

虽然JLS(Java语言规范)并没有要求,但是按照惯例,错误往往被JVM保留下来使用,以表明资源不足、约束失败,或者其他使用程序无法继续执行的条件。由于这已经是个几乎被普遍接受的惯例,因此最好不要再实现任何新的Error子类。因此,你实现的所有未受检的抛出结构都应该是RuntimeException的子类(直接的或者间接的)。不仅不应该定义Error子类,甚至也不应该抛出AssertionError异常。

要想定义一个抛出结构,使它不是Exception、RuntimeException或Error的子类,这也是可能的。JLS并没有直接规定这样的抛出结构,而是隐式的指定了:从行为意义上讲,它们等同于普通的受检异常(即Exception的子类,但不是RuntimeException的子类)。那么,什么时候应该使用这样的抛出结构呢?一句话:永远也不会用到。它与普通的受检异常相比没有任何益处,只会困扰API的用户。

API的设计者往往会忘记,异常也是个完全意义上的对象,可以在它上面定义任意的方法。这些方法的主要用途是为了捕获异常的代码而提供额外的信息,特别是关于引发这个异常条件的信息。如果没有这样的方法,程序员必须要懂得如果解析“该异常的字符串表示法”,以便获得这些额外信息。这是极为不好的做法(详见第12条)。类很少会指定它们的字符串表示法中的细节,因此,对于不同的实现及不同的版本,字符串表示法大相径庭。由此可见,“解析异常的字符串表示法”的代码可能是不可移植的,也是非常脆弱的。

因为受检异常往往指明了可恢复的条件,所以,对于这样的异常,提供一些辅组方法尤其重要,通过这些方法,调用者可以获得一些有助于恢复的信息。例如,假设因为用户资金不足,当他企图购买一张礼品卡时导致失败,于是抛出一个受检的异常。这个异常应该提供一个访问方法,以便允许客户查询所缺的费用金额,使得调用者可以将这个数值传递给用户。关于这个主题的更多详情,请参阅第75条。

总而言之,对于可恢复的情况,要抛出受检异常;对于程序错误,要抛出运行时异常。不确定是否可恢复,则抛出未受检异常。不要定义任何既不是受检异常也不是运行时异常的抛出类型。要在受检异常上提供方法,以便协助恢复。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,047评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,807评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,501评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,839评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,951评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,117评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,188评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,929评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,372评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,679评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,837评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,536评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,168评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,886评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,129评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,665评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,739评论 2 351

推荐阅读更多精彩内容