Effective-Java_读书笔记11

71 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情

58 Use checked exceptions for recoverable conditions and runtime exceptions for programming errors 受检异常用于可恢复的场景, 运行时异常用于表示编程错误

结论

  1. 异常分为受检异常和运行时异常, 其中运行时异常包括RuntimeException和Error.
  2. RuntimeException和Error基本一样, 区别在于Errors是JVM用于表示异常, 所以平常我们(强制)不使用Error表示程序异常.
  3. 受检异常表示程序可恢复. 运行异常表示不可恢复, 需要立刻终止.

详述

到底要抛出哪种异常? 这个问题真的十分困扰. 书中的观点参考性其实不大:

  1. 受检异常用于可恢复的场景, 即抛出受检异常是为了强制让调用方处理异常, 并对异常进行恢复.
  2. 而运行时异常表示程序代码错误, 可以理解为没有按照接口文档调用接口, 比如参数传的不对. 运行时异常同时也表示程序无法再运行下去了, 只能终止.

看起来两种异常区别很大, 但是实际上什么是可恢复场景是没有一个准确的定义的. 作者建议在不清楚使用哪种异常时, 使用运行时异常.

还有一种论调是: 抛出受检异常是想让客户端注意到方法可能会抛出这样的异常, 如果是运行异常可能由于开发人员没有关注导致系统异常.

这种情况其实可以向上述观点上靠. 抛出的异常是可恢复的么? 如果不可恢复, 那开发人员关注也只是换一种异常抛出. 如果是可恢复的确实需要抛出受检异常.

对于换一种异常抛出其实在平常工作中使用的非常多, 比较常见的场景是: 内部错误有自己的错误码, 接口不会将内部细节返回给客户端, 所以会在某处将内部异常码转换为外部异常码, 所以这里经常将内部错误包装为受检异常, 然后在转换的地方捕获并处理, 其他情况直接向上抛出.

上述情况偏向于通用的处理方案, 个人认为应该使用统一的处理逻辑(比如切面)处理, 而不是通过抛出受检异常由开发人员控制转换.

关于恢复场景, 有个矛盾的地方. 场景可不可以恢复是由调用方决定的, 接口方(或者方法定义)在定义时不可能知道自己的调用方的使用场景是否可以恢复, 所以为什么要接口方来决定是否抛出受检异常?

总结

  1. 受检异常和运行时异常都表示异常, 使用方式也类似.
  2. 二者的区别主要在使用语义上, 受检异常强制客户端处理异常, 尽可能恢复异常; 运行时异常表示程序异常, 通常是由于没有正确调用方法导致, 认为是不可恢复的.
  3. 在犹豫不知道使用哪种异常时, 就用运行时异常吧~

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情