开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情
58 Use checked exceptions for recoverable conditions and runtime exceptions for programming errors 受检异常用于可恢复的场景, 运行时异常用于表示编程错误
结论
- 异常分为受检异常和运行时异常, 其中运行时异常包括RuntimeException和Error.
- RuntimeException和Error基本一样, 区别在于Errors是JVM用于表示异常, 所以平常我们(强制)不使用Error表示程序异常.
- 受检异常表示程序可恢复. 运行异常表示不可恢复, 需要立刻终止.
详述
到底要抛出哪种异常? 这个问题真的十分困扰. 书中的观点参考性其实不大:
- 受检异常用于可恢复的场景, 即抛出受检异常是为了强制让调用方处理异常, 并对异常进行恢复.
- 而运行时异常表示程序代码错误, 可以理解为没有按照接口文档调用接口, 比如参数传的不对. 运行时异常同时也表示程序无法再运行下去了, 只能终止.
看起来两种异常区别很大, 但是实际上什么是可恢复场景是没有一个准确的定义的. 作者建议在不清楚使用哪种异常时, 使用运行时异常.
还有一种论调是: 抛出受检异常是想让客户端注意到方法可能会抛出这样的异常, 如果是运行异常可能由于开发人员没有关注导致系统异常.
这种情况其实可以向上述观点上靠. 抛出的异常是可恢复的么? 如果不可恢复, 那开发人员关注也只是换一种异常抛出. 如果是可恢复的确实需要抛出受检异常.
对于换一种异常抛出其实在平常工作中使用的非常多, 比较常见的场景是: 内部错误有自己的错误码, 接口不会将内部细节返回给客户端, 所以会在某处将内部异常码转换为外部异常码, 所以这里经常将内部错误包装为受检异常, 然后在转换的地方捕获并处理, 其他情况直接向上抛出.
上述情况偏向于通用的处理方案, 个人认为应该使用统一的处理逻辑(比如切面)处理, 而不是通过抛出受检异常由开发人员控制转换.
关于恢复场景, 有个矛盾的地方. 场景可不可以恢复是由调用方决定的, 接口方(或者方法定义)在定义时不可能知道自己的调用方的使用场景是否可以恢复, 所以为什么要接口方来决定是否抛出受检异常?
总结
- 受检异常和运行时异常都表示异常, 使用方式也类似.
- 二者的区别主要在使用语义上, 受检异常强制客户端处理异常, 尽可能恢复异常; 运行时异常表示程序异常, 通常是由于没有正确调用方法导致, 认为是不可恢复的.
- 在犹豫不知道使用哪种异常时, 就用运行时异常吧~
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情