为啥不建议用 try catch

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥不建议用 try catch相关的知识,希望对你有一定的参考价值。

一句话解释:
try catch机制非常好。那些觉得try catch不行的人,是他们自己的水平有问题,无法理解这种机制。并且这群人写代码不遵守规则,喜欢偷懒,这才造成try catch不好的错觉。
详细解释:
1.程序要健壮,必须要设计报错机制。
最古老,也是最常见的,比如:
bool CreateFile( );
//如果创建文件失败就返回false,否则返回true。
这种报错方式,显然不好。因为它没有给出产生错误的具体原因。
2.改进:一个函数或过程,会因为不同的原因产生错误,报错机制必须要把这些错误原因进行区分后,再汇报。
比如:
int CreateFile():
//如果创建成功就返回1.
//如果是因为没有权限,导致失败,返回-1。
//如果是因为文件已经存在,导致失败,返回-2。
//如果是因为创建文件发生超时,导致失败,返回-3。
这样看上去,比【1】要好些,至少指出了比较具体的失败原因,但是,还不够。
参考技术A 为什么不建议用 try catch

能够捕获的异常都继承自Exception类。 需要以try-catch捕获的是"可检查"异常,所谓"可检查"异常,是指我们应该自行处理的异常。至于处理的手段,要么加以控制(try catch),要么通告(throws)他们有可能产生。通常,应捕捉那些已知如何处理的异常,而通告那些不知如何处理的异常。 java的异常处理机制要求程序员必须捕捉"可检查"异常并提供处理方法,或者向更上层抛出该异常。 try-catch能解决的问题就是处理可能出现的异常,打个比方,考虑如下代码: public void go() File file=new File("d:\\a.txt"); FileInputStream fis=null; try fis=new FileInputStream(file); catch (FileNotFoundException ex) System.out.println("file not found"); ex.printStackTrace(); if(fis!=null)//如果找到了文件 …… 代码作用是打开一个文件,如果找不到文件(即捕获到了FileNotFoundException),就给出提示。而找不到文件这样的异常,就属于可能会出现的、可以处理的异常,以这段代码为例try-catch的作用就在于系统找不到文件时不会导致程序出错终止,而是继续往下运行。多线程为什么用try-catch,其实也是同样的道理。
参考技术B 这个要看如何定义。如果过多,是因为你的可能报错的地方比较多而是用try catch,这样当错误出现时,反而会比较方便的定位错误的位置。建议,将try catch 用的细致化,明确化。如果是滥用,这样只是会让程序的可读性变的很糟糕,当程序报错,也无法快速准确的定位。希望对你有所帮助。本回答被提问者采纳

为啥使用 NSError 间接参数而不是 @try/@catch/@finally

【中文标题】为啥使用 NSError 间接参数而不是 @try/@catch/@finally【英文标题】:Why use NSError indrect parameters instead of @try/@catch/@finally为什么使用 NSError 间接参数而不是 @try/@catch/@finally 【发布时间】:2018-02-01 03:01:44 【问题描述】:

从其他问题,我可以看到建议NSError用于可恢复的错误,@throw/@catch/@finallyNSException应该用于致命错误。

这对我来说毫无意义。为什么要使用NSException 来处理致命错误? 关键是他们可以被抓到!如果抓到他们不是重点,那为什么还有@try/@catch系统呢?为什么不只是NSLogexit(1),然后就结束了?

NSError 也很笨拙,这让我更喜欢@throw/@catch/@finally

是什么激励使用其中一个而不是另一个?

【问题讨论】:

你在内部做什么是你的事。但是 NSException 并不那么容易被捕获。假设你的代码是从 Swift 中使用的。 Swift 程序员可以捕获你的 NSError 但不能捕获你的 NSException。 @matt “没那么容易被抓住。”为什么?是的,我知道 Swift 不支持 NSException,这对我来说也毫无意义。我最好的猜测是 NSError 已经是主要的错误处理机制,所以没有必要实现对在 swift 中捕获 NSException 的支持。但这并不能解释为什么 NSError 在 Swift 之前占主导地位。 假设 Cocoa 抛出一个 NSException。通常发生的不是你抓住它;而是你抓住了它。通常发生的事情是你崩溃了。但是当 Cocoa 给你一个 NSError 时,它会向你发送一条消息,解释为什么它不能返回请求的值。这些是 Cocoa 设计模式。 那么 NSError 占主导地位是因为它更容易被忽略? @Alexander 它可以被忽略的事实是语言规则的副产品,而不是框架的约定(例如,如果 Obj-C 像 Swift 那样有错误规则,你就不会可以忽略它们)。也可以在 Matt 的回答中查看我的 cmets — 这里的主要区别在于,一个是针对 programmer 错误,另一个是针对正常运行时的“预期”错误。 【参考方案1】:

这些是长期存在的 Cocoa 设计模式。

从您对值的请求(例如“请尝试从该字符串创建 URL”)以良好的顺序(通常通过间接方式)返回 NSError 对象。当无法提供该值时,它会被有效地替换,实际上是一个精心制作的消息,一个可能包含您可以向用户展示的文本的信息包,关于用户如何从这种情况中恢复的建议等等。

发生 NSException 是因为 程序员 犯了严重错误。它代表了一个致命的问题,因此它渗透到链条上并使程序突然结束。 it 包含的消息仅适用于程序员

【讨论】:

这正是它的要点。 NSException 表示 programmer 错误;他们可以被抓住,但不是故意的。并非 Cocoa 框架的每个部分都支持从抛出的异常中恢复,并且许多部分都被假定为结束程序执行。如果没有special flag,ARC 也不会尝试在异常处理代码附近重新排序retains 和releases,以确保在实际捕获到异常时不会泄漏对象(因为假设是无论如何,这个过程很快就会结束)。 所有可恢复的错误,然后,通过NSError,其 MO 是最终用户可呈现性。错误可能很严重,但如果不是由于程序员错误,应该以某种方式处理并呈现给用户(这就是为什么NSErrors 被本地化到这样的程度)。 @Alexander @catch 并不总是内置在语言中,而 IIRC,在NSException 切换到使用 C++ 异常机制之前,它们的捕获和抛出成本比现在高。但除了人体工程学之外,我认为这并没有真正深刻的技术原因——这主要是一种哲学选择。程序员错误相对较少,但运行时错误很常见,并且应该始终是用户可呈现的。通过引用返回错误很便宜,尤其是与异常相比(过去更是如此);其他一切都是围绕约定建立的。 目前很难找到这方面的好资料,但我相信 @try@catch 是在 ObjC 2.0 中引入的,那时,NSException 基础架构切换到使用C++ 异常机制。到目前为止,我认为NSException 是建立在setjmp/longjmp 之上的。这可能是也可能不是您正在寻找的技术推理...... 顺便说一句,“通常的模式”有一些例外(!)。例如,+[NSExpression expressionWithFormat:] 如果格式字符串格式不正确(在 Swift 中无法捕获,并且使 NSExpression 对于用户提供的输入几乎无用),则会引发异常。【参考方案2】:

苹果说:

重要提示:您应该保留将异常用于编程或意外的运行时错误,例如越界集合访问、尝试改变不可变对象、发送无效消息和断开连接到窗口服务器。您通常在创建应用程序时而不是在运行时处理这些类型的异常错误。

 

错误对象 (NSError) 和 Cocoa 错误传递机制是在 Cocoa 应用程序中传达预期错误的推荐方式,而不是异常。

来源:Exception Programming Topics

【讨论】:

查看我的问题的最后一行 @Alexander Apple 不会说明原因,也许是框架内部的某些东西。我从经验中知道:如果你不遵守苹果的规则,你就会遇到麻烦。这也是其他问题推荐NSError的原因。 现在 Apple 说“使用 Swift”和“错误处理是响应程序中的错误条件并从错误条件中恢复的过程。Swift 为抛出、捕获、传播和操作可恢复对象提供一流的支持运行时出错。”。也许将来框架会在 Swift 中,NSError 会消失。

以上是关于为啥不建议用 try catch的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 NSError 间接参数而不是 @try/@catch/@finally

用powershell的try catch, 为啥try里面出现异常,catch 捕获不到呢?

Powershell错误处理,try catch finally

编写高质量代码改善C#程序的157个建议——建议64:为循环增加Tester-Doer模式而不是将try-catch置于循环内

try语句可以套try语句?

何时使用 try/catch 块?