合理使用异常

阅读经典——《Effective Java》10

异常是面向对象编程中非常重要的一环,合理使用异常,可以提高程序的可读性、可靠性和可维护性。本文我们来讨论在Java中如何合理使用异常。

  1. 只针对异常的情况才使用异常
  1. 正确使用受检异常和运行时异常
  2. 优先使用标准的异常
  3. 异常转译和异常链

只针对异常的情况才使用异常

异常应该只用于异常的情况,而不是正常的控制流。任何试图使用异常来简化正常控制流的行为都是不值得提倡的。考虑下面的情况:

try {
  Iterator<Foo> i = collection.iterator();
  while(true) {
    Foo foo  = i.next();
    ...
  }
} catch (NoSuchElementException e) {
}

使用异常检查迭代器是否遍历结束,这是很愚蠢的做法,可读性很差,而且在性能上可能更糟。Iterator作为一个设计良好的API,不可能鼓励用户这样使用,因此它提供了hasNext方法用来显式判断遍历是否结束。这也给API设计者一定的启发,不要让你的用户被迫使用异常来实现正常的控制流。

正确使用受检异常和运行时异常

Java程序设计语言提供了三种可抛出结构(throwable):受检异常(checked exception)、运行时异常(runtime exception)和错误(error)。

受检异常必须必须被try-catch块包围,用户有责任处理这个异常或继续向外抛出。这是对API用户的一种暗示:抛出异常是该方法的一种可能结果,请务必小心。

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

错误往往被JVM保留用于表示资源不足、约束失败、或者其它使程序无法继续执行的条件。这是系统错误,我们不应该继承Error

自定义异常也是一个完整意义上的对象,因此我们可以在它上面定义各种方法,以提供额外的信息供用户查看。

优先使用标准的异常

Java类库为我们提供了一组基本的运行时异常,它们可以满足绝大多数API的异常抛出需求。我们应该尽量重用它们,而不是自定义全新的异常。因为这会使你的API更容易被用户理解,而且降低类加载的开销。常用的异常列表如下。

异常 使用场合
IllegalArgumentException 非null的参数值不正确
IllegalStateException 对于方法调用而言,对象状态不合适
NullPointerException 在禁止使用null的情况下参数值为null
IndexOutOfBoundsException 下标参数值越界
ConcurrentModificationException 在禁止并发修改的情况下,检测到对象的并发修改
UnsupportedOperationException 对象不支持用户请求的方法

异常转译和异常链

如果高层无法处理低层抛出的异常,就应该继续抛出。但抛出时建议使用异常转译:更高层的实现应该捕获低层的异常,同时抛出可以按照高层抽象进行解释的异常。

下面的异常转译例子取自AbstractSequentialList类,在这个例子中,按照List<E>接口中get方法的规范要求,异常转译是必需的。使用该类的用户应该看到IndexOutOfBoundsException而不是NoSuchElementException

/**
 * Returns the element at the specified position in this list.
 * @throws IndexOutOfBoundsException if the index is out of range
 *         ({@code index < 0 || index >= size()}).
 */
public E get(int index) {
  ListIterator<E> i = listIterator(index);
  try {
    return i.next();
  } catch (NoSuchElementException e) {
    throw new IndexOutOfBoundsException("Index:" + index);
  }
}

上面这种写法唯一的缺点是会丢失低层异常信息,不过我们可以用异常链来弥补这个缺点。我们的自定义异常应该提供一个接收Throwable参数的构造方法,把该参数传给父类的构造器,代码如下。这样用户使用我们的API时就可以用getCause访问到异常的底层原因。

// Exception with chaining-aware constructor
class HigherLevelException extends Exception {
  HigherLevelException(Throwable cause) {
    super(cause);
  }
}

关注作者文集《Effective Java》,第一时间获取最新发布文章。

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

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,818评论 25 707
  • 第五十七条、只针对异常的情况才使用异常 不要优先使用基于异常的模式:因为异常机制的设计初衷是用于不正常的情况,所以...
    Timorous阅读 665评论 0 1
  • “近日,我市发生多起入室抢劫杀人事件,警方提醒应……” 他的嘴角上扬着,脑中酝酿着一个疯狂的计划。 他刚潜进一...
    与世同君阅读 193评论 0 0
  • 看着身边的小朋友一天天长大 总会有一种恍惚感 似乎还是小时候 她们呀呀学语 转眼 一个个都变得婷婷玉立 拍下以下照...
    悠然小妖阅读 541评论 0 8
  • 郭相麟 节日里大家欢聚一堂,汽车挤满了道路,交警忙得头晕脑胀,进行道路疏通,车子走走停停,车子挤挤攘攘,驾车的人...
    郭相麟阅读 213评论 0 0