方式 1 和方式 2 的却别到底在哪里?

2019-11-16 11:13:45 +08:00
 Simle100

在开发中对于 a/b,这样的表达式,我们要做 b 的校验。但有两种方式: 方式 1: if ( b == 0 ) { // 提示除数不能为 0 } 方式 2: try{ a / b; } catch (ArithmeticException e){ // 提示除数不能为 0 } 这两种方式的差别是什么?是不是所有的处理异常的代码都被方式 1 取代?如果是这样,那么异常机制存在的理由是什么? 请大佬赐教。

6430 次点击
所在节点    Java
47 条回复
712e1959
2019-11-16 11:20:14 +08:00
省劲儿。
Simle100
2019-11-16 11:23:02 +08:00
@projectceiling 我提的问题,跟这个差不多:一个方法的参数,C 里面好像是一堆的 if else 判断参数是否合法,不合法就返回一个没有实际意义的值

但在 java 里面有异常机制,当参数不合法的时候,究竟是 if else 一样判断后返回一个值

还是直接来个 Exception ?

如果是 if else 的话,有什么好处 ?

如果是 exception 的话,又有什么好处 ?

或者是根据不同情况来定 ?
Simle100
2019-11-16 11:23:44 +08:00
@projectceiling 处理异常的代码不是更复杂吗?这股劲省在哪里了啊?
vikeria
2019-11-16 11:38:04 +08:00
异常机制蛮消耗性能的
hdbzsgm
2019-11-16 11:41:42 +08:00
EAFP 与 LBYL 是两种编程风格 用哪个都行
leeg810312
2019-11-16 11:44:01 +08:00
try catch 在执行时比 if 的资源消耗大很多,能够用 if 解决不要用 try
Simle100
2019-11-16 11:51:31 +08:00
我自己的业务代码中几乎没有 try catch 语句,但是 Java 许多开源框架里面有许多 try catch,所有我在想是不是我的代码有问题?@leeg810312 @hdbzsgm @vikeria
wysnylc
2019-11-16 11:51:42 +08:00
9120 年了还有人在说不推荐用异常异常性能差呢哈哈哈哈,要是异常性能这么差为啥 jvm 不优化或者不去掉呢?
我推荐使用 2,因为可以准确捕获到除数不能为 0 的异常可以针对的处理,而且并不是每次都为 0 那么每次都多个 if 判断谁的性能差?
jvm 存在的意义就是给你抹除掉在 C 中因为考虑性能而需要在代码中做的种种优化,让开发者更注重于代码的健壮性和语义而不是在开发阶段考虑所谓的"性能",诚然是需要考虑性能但是是需要在并发环境下考虑而不是在这微不足道的 if else 上
ysoserious
2019-11-16 11:53:10 +08:00
方式 1 要考虑到各种可能的异常情况(比如你举的例子中就没有判断 null==b)

而方式 2 可以直接把程序异常抛出去让人看, 缺点是不一定人人都看得懂错误信息, 如果你针对错误情况给出人人都能看得懂的提示的话, 又回到方式 1 去考虑各种异常情况了.
wysnylc
2019-11-16 11:54:43 +08:00
很多语言都存在异常处理机制,都是推荐使用 EAFP 方式,因为这样开发者可以注重于开发正常的逻辑而不是时时刻刻考虑 if else 判断,LBYL 方式会导致正常的逻辑穿插各种检查代码反而导致难以读懂
这里有一篇分析你可以看看 http://ju.outofmemory.cn/entry/367391
murmur
2019-11-16 11:55:30 +08:00
@wysnylc 这个东西我持保留意见,我见过那种代码,除了 mybatis 提供的转义之外,什么参数都不校验,数据错了插不进去是异常,流程或者权限错了工作流报异常。。小业务是没问题,但是总看着觉得不舒服
wysnylc
2019-11-16 12:05:07 +08:00
@murmur #11 那么在方法中将返回值定义成各种对象里面包含对应的状态码和结果就好了吗?试想一个场景,用户购买物品失败如果不使用异常控制则需要在 serverice 方法的返回值中定义 code message result 来告知上层方法本次失败的原因,这种设计是不是比异常控制更恶心?
而用异常控制就很简单了,不会因为需要兼容失败情况而修改方法返回值,只需要捕获不同的异常和异常自定义信息就可以
孰优孰劣,一用便知
taogen
2019-11-16 12:05:52 +08:00
知道异常输入值是什么可以用 if 判断,不知道用 try catch。如,SQL 异常,数据库连接异常等。

if else 和 try catch 目的都是对正常和异常情况分开处理。
chendy
2019-11-16 12:11:31 +08:00
明显用 1 不用 2,1 比 2 清晰太多了…只因为清晰,无关性能(性能其实真的差,但是和 io 比还是微不足道
从 crud 的角度看,异常更多时候是用来抛的,手动 catch 的情况并不多
遇到数据错误,逻辑不对,直接抛个异常中断业务,最外层全局捕获转换报错信息发出去
wysnylc
2019-11-16 12:12:16 +08:00
@leeg810312 #6
@vikeria #4 关于异常性能的问题麻烦看这里:https://blog.csdn.net/wenbingoon/article/details/8240862
直接拉到最底下有这么几句话
1。Exception 的性能是差,原因在于 Throwable    fillInStackTrace()方法()  -----  public synchronized native Throwable fillInStackTrace();
2. 可以通过改写业务异常基类的方法,提升性能
3。try...catch 和 if...else 的性能开销在同一数量级
hdbzsgm
2019-11-16 12:14:02 +08:00
@Simle100 #7 因为角度不同 callee 跟 caller 的处理边界或者处理异常的思路是有区分的 但是一个原则就是要给 caller 反馈到足够的错误信息 你写 if/else 去反馈 框架用 try/catch 去反馈 都可以
optional
2019-11-16 12:24:09 +08:00
JAVA 又没有 some(x)这种 enum
potcode99
2019-11-16 13:41:25 +08:00
防御式编程和 Java 语言特性的区别,换个不支持异常捕获的语言就只能用 if else,if 的写法更通用一些吧
felixlong
2019-11-16 13:41:54 +08:00
@wysnylc jvm 再优化能优化到比 if 还好?不要想当然的以为 jvm 可以解决一切问题。
vikeria
2019-11-16 14:08:24 +08:00
@wysnylc 异常处理的性能消耗主要还是在堆栈信息的跟踪上,打印有利于问题定位,在现在看确实微不足道,只是略提一下。正常编码规范一般不会推荐在异常处理中做业务逻辑,实际操作中,还是具体问题具体分析吧。每个人的理解和编码习惯不同,有利于代码健壮性和可维护性即可。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/620135

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX