try catch 和 if 在处理程序可能的出错上有什么区别?

2019-06-24 15:04:13 +08:00
 aoscici2000

比如说抽取文章前 100 字作为简介, 两种方法有什么区别


String content = ".........."

try {
    content = content.substring(0, 100)
} catch (StringIndexOutOfBoundsException e) {
    // pass
}

if ( content.length() > 100 ) {
    content = content.substring(0, 100)
}

3978 次点击
所在节点    Java
26 条回复
a719114136
2019-06-24 15:06:18 +08:00
区别就是一个 try catch 和一堆 if。
当然 java 的特性,很多时候你必须 try catch
xiaopang132
2019-06-24 15:24:58 +08:00
如果程序出现了 catch 中的异常,程序会继续往下跑,但是如果 if 中出现了异常,程序会停止.
linxb
2019-06-24 15:34:25 +08:00
try catch 可以处理一些程序中断的异常
questionlin
2019-06-24 15:35:27 +08:00
try...catch 的设计是,一个程序只有一个,一般在最外层,统一处理所有错误
chendy
2019-06-24 15:37:45 +08:00
区别是第二种更已读,性能也更好
除非必要否则不要用捕获异常的方式做业务
msg7086
2019-06-24 15:38:30 +08:00
异常一般用在程序员假定本应正常工作的情况; if 一般用在程序员假定本来就可能会触发的情况。
比如,如果 content 是用户输入,那么用户输入多少字都有可能,所以用 if。
如果 content 是某个专门输出大量文章的函数输出的产物,正常情况下都应该输出超过 100 字内容的,如果少于 100 字那就是程序工作不正常了,这种时候就可以用异常。

异常说白了也是 if 触发的。substring 里有 if (length <= 100) throw StringIndexOutOfBoundsException。
q8164305
2019-06-24 15:40:59 +08:00
异常一般只用在程序员不能控制的地方,如能控制,尽量不用异常
geelaw
2019-06-24 15:44:19 +08:00
@a719114136 #1
@questionlin #4
这个想法非常危险,如果不细致地处理异常,外面的处理器通常不能明白到底发生了什么,如果这时继续运行将会带来不可预料的结果。

@msg7086 #6
不全是,比如所有的网络访问都应该被假定可以失败,但是很多高级语言中只能通过 try...catch 来捕获异常(因为错误代码已经被转换为异常)。

——————

回到题主提到的问题,第二种写法效率更好。
palmers
2019-06-24 15:46:25 +08:00
1. 在 java 中, 异常栈是有成本的, 在这段代码里, 很明显的 if 判断的成本远远大于异常栈的成本;
2. 在程序设计上, 能够提前预知的异常都不应该依赖 catch 去帮你捕获;很多 java 程序设计的书籍也有提到不应该利用异常栈做流程处理, 在这里也是类似的道理;
3. 使用 try...catch 一般都是为了容错,而不是为了用来做类似判断的逻辑处理;
palmers
2019-06-24 15:47:27 +08:00
@palmers 对不起 第一条写反了 反正大概意思你明白就行
zqx
2019-06-24 15:50:04 +08:00
正常的语言里,try 都是用于捕获未知的错误,如果你都知道这个表达式在某些条件下一定会抛出错误,那就应该用判断条件说明它
kzfile
2019-06-24 15:54:40 +08:00
错误天然可以传递
使用 if 你一般要在发生错误的上一层处理错误.
但使用错误传递,你可以有更多的选择
lithiumii
2019-06-24 16:19:55 +08:00
java 不懂,反正 py 是偏好 EAFP ( Easier to ask for forgiveness than permission,字面意思:请求原谅比请求许可更容易)多于 LBYL ( Look before you leap,字面意思:跳之前先看清楚),然后 EAFP 的用法一般就是 try 后面再 catch 已知的特定错误(反正你没事儿别一口气 catch 所有的错误就是了)。
NoKey
2019-06-24 16:27:26 +08:00
if 能判断的,你用 try 去搞,你这个写法,我还是第一次见啊。。。
niubee1
2019-06-24 16:34:50 +08:00
一般的语言,只能 return 一个值, 而错误包含了 3 个信息,1 是是不是错了 2 是是啥错 3 是出错的地方提供了啥信息。 你说一个强类型的语言要怎么优雅的弥合这个鸿沟?而异常机制是另开通道来把正常逻辑和错误处理逻辑解耦开的方式, 保证了正常的业务逻辑不受到错误的影响。 而基于返回值的方式处理错误,是等于把处理错误作为了业务逻辑必须关心的话题了, 这样简单直接, 但是面对复杂的容易出错的部分耦合在一起的逻辑就会显得很杂乱,因为内部正常逻辑和错误处理逻辑是交织在一起的。
rizon
2019-06-24 16:43:29 +08:00
真较真这个也没啥意思,从结果上看似乎一样,但是每个语句都有自己的使命,就算其他语句能达到这个效果,但毕竟不是为此而生的。
你要真说 try 代替 if 这种非主流做法有什么坏处,也是有很多的。
catch 的 oob 异常你怎么知道是 endIndex 超出了,还是 beginIndex 超出了?
在一些其他的方法里,如果你不判断而是直接运行,看看结果如何,那么有些事情在方法里被执行了,然后才抛出问题,小了说这就是浪费,而对于有副作用的函数那就是直接不对了。
FrankHB
2019-06-24 18:29:38 +08:00
Locality 和 exception/error neutrality 都没人提就算了,影响 signature 都不管了(好吧好像有一位提了)? Java、Java ……
要跨过程传播错误状态,你一个个改返回类型?还是先发明个 longjmp ?(习惯没事人肉糟蹋 throws 的当我没说。)
当然 LZ 这种立即原地 catch 的玩意儿就是 try 反面教材。
pkookp8
2019-06-24 18:42:06 +08:00
@niubee1 我觉得所有这三个信息都可以归结于返回 0 或非 0 来表示。
只要有提前约定
blless
2019-06-24 19:08:26 +08:00
就感觉很多人连错误处理都不会 一般业务最上层有 try catch,程序内部基本不用了,尽管抛出异常就是了,最上层处理异常就好。业务超出本机控制代码,一般都要额外 try catch,比如网络,磁盘之类的 IO 请求,需要根据业务处理直接抛出还是重试。按我理解一个应用三层 try catch 就够用了
annoymous
2019-06-24 19:21:33 +08:00
EAFP 与 LBYL 是两种编程风格 爱用哪个用哪个

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

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

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

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

© 2021 V2EX