提前条件判断VS捕获运行时异常:哪种除法代码写法更合理?
提前条件判断 vs 捕获运行时异常:哪种更合理?
这是个非常经典的编程风格问题,其实没有一刀切的标准答案——核心要看你的代码意图和具体的场景上下文。咱们一步步拆解你的例子:
一、基础除法场景的两种写法
1. 提前做条件判断(if (divisor != 0))
这种写法走的是主动防御路线,属于“预判可能的错误,提前规避”。它的优势很明显:
- 代码逻辑直观到爆炸:读代码的人一眼就能get到“除数不能为0”这个前置规则,理解成本极低
- 避免了异常抛出/捕获的额外开销(虽然你说不考虑性能,但实际开发里这也是个实实在在的点)
- 完美贴合**“失败前置”**的编程原则:把错误检查放在业务逻辑前面,让正常流程的代码更干净、更聚焦
这种写法最适合你能完全控制输入,且“除数为0”是可预见的非法输入的场景——比如除数来自用户表单输入,或者你自己系统内部生成的数值,你有能力提前做校验。
2. 捕获运行时异常(try-catch)
这种写法的思路是**“先执行,出问题再收拾烂摊子”**。它的适用场景其实很窄:
- 你完全没法提前预判所有可能的错误:比如除数来自第三方接口、外部文件,或者有一堆复杂到没法提前枚举的边界情况(比如除了0,还有整数溢出?不过int除法溢出也会抛出
ArithmeticException) - 异常情况属于罕见的、完全意外的错误,而不是常规的业务分支
回到你的除法例子,用try-catch处理除数为0其实有点“杀鸡用牛刀”——因为除数为0是100%可预见的,提前判断的代码既简洁又符合直觉,没必要绕到异常处理上。
二、自定义divide方法后的两种写法
你后来封装的divide方法,把“除数为0”的校验和异常抛出做了封装,这时候两种写法的核心区别就变成了**“谁来承担输入校验的责任”**:
1. 调用方提前判断,再调用方法
这种写法的逻辑是:调用方明确知道方法的输入契约(除数不能为0),主动承担校验责任。好处是:
- 符合**“契约式编程”**的思路:调用方遵守方法的输入规则,方法本身只专注于核心的除法逻辑(或者在契约被违反时抛出异常来“追责”)
- 避免了不必要的异常抛出,让正常流程的代码更顺畅
2. 调用方直接用try-catch包裹调用
这种写法的逻辑是:调用方依赖方法来处理输入校验,自己只负责处理异常结果。但这里要注意一个坑:
- 你的
divide方法已经明确抛出了ArithmeticException,这等于在告诉所有调用方:“我只接受合法的除数,非法输入我会直接抛异常”——如果调用方无视这个契约,非要靠catch异常来处理业务分支,会让代码的意图变得模糊:别人读代码的时候会疑惑,“这里为什么要catch异常?是不是还有其他我没考虑到的错误场景?” - 只有当调用方确实没法提前校验(比如除数是动态生成的、完全没法提前获取)时,这种写法才说得通
最后给你总结几个选择原则
- 如果错误是可预见、可提前校验的(比如除数为0),优先用提前条件判断——代码更清晰,也更符合大多数开发者的编程直觉
- 如果错误是不可预见、罕见的,或者异常情况本身就是业务逻辑的一部分(比如某些API调用失败需要捕获后做降级处理),再考虑用try-catch捕获异常
- 自定义方法时,要先明确方法的职责:如果方法是“严格执行除法,非法输入直接抛异常”,那调用方最好提前做校验;如果方法是“封装除法逻辑,包括处理非法输入”,那应该把校验和错误处理都塞进方法内部,别让调用方再去折腾catch
内容的提问来源于stack exchange,提问作者Maximillian
相关产品推荐
相关产品推荐

