`
悲伤的小脑
  • 浏览: 9206 次
  • 性别: Icon_minigender_1
  • 来自: 株洲
社区版块
存档分类
最新评论

try catch与程序封装

    博客分类:
  • java
 
阅读更多
本文引用于知乎:http://www.zhihu.com/question/29459586
问题:为什么不建议用 try catch?

pig pig ,网管
178 人赞同
不问是不是,就问为什么。这个问题看来需要从头说起。

一句话解释:
try catch机制非常好。那些觉得try catch不行的人,是他们自己的水平有问题,无法理解这种机制。并且这群人写代码不遵守规则,喜欢偷懒,这才造成try catch不好的错觉。

详细解释:
1.程序要健壮,必须要设计报错机制。
最古老,也是最常见的,比如:
bool CreateFile( );
//如果创建文件失败就返回false,否则返回true。
这种报错方式,显然不好。因为它没有给出产生错误的具体原因。

2.改进:一个函数或过程,会因为不同的原因产生错误,报错机制必须要把这些错误原因进行区分后,再汇报。
比如:
int CreateFile():
//如果创建成功就返回1.
//如果是因为没有权限,导致失败,返回-1。
//如果是因为文件已经存在,导致失败,返回-2。
//如果是因为创建文件发生超时,导致失败,返回-3。
这样看上去,比【1】要好些,至少指出了比较具体的失败原因,但是,还不够。

3.很多情况下,函数需要把详细的原因,用字符串的方式,返回:
class Result
{
....int State;//同【2】
....string ErrorMessage;//如果失败,这里将给出详细的信息,如果有可能,应该把建议也写上去。
}

Result CreateFile();
//如果创建成功,返回的Result,State为1,ErrorMessage为null。
//如果是因为没有权限,导致失败,返回的Result,State为-1,ErrorMessage为"用户【guest】没有权限在【C:\】这个目录下创建该文件。建议您向管理员申请权限,或者更换具有权限的用户。"。
//如果是因为文件已经存在,导致失败,返回的Result,State为-2,ErrorMessage为"文件【C:\abc.txt】已经存在。如果需要覆盖,请添加参数:arg_overwrite = true"。
//如果是因为创建文件发生超时,导致失败,返回的Result,State为-3,ErrorMessage为"在创建文件时超时,请使用chkdsk检查文件系统是否存在问题。"。

4.我个人推崇上面这种方式,完整,美观。但是这种流程,容易与正常的代码混在一起,不好区分开。因此,Java、C#等设计了try catch这一种特殊的方式:
void CreateFile()
//如果创建成功就不会抛出异常。
//如果是因为没有权限,导致失败,会抛出AccessException,这个Exception的Msg属性为"用户【guest】没有权限在【C:\】这个目录下创建该文件。建议您向管理员申请权限,或者更换具有权限的用户。"。
//如果是因为文件已经存在,导致失败,会抛出FileExistedException,这个Exception的Msg属性为"文件【C:\abc.txt】已经存在。如果需要覆盖,请添加参数:arg_overwrite = true"。
//如果是因为创建文件发生超时,导致失败,会抛出TimeoutException,这个Exception的Msg属性为"在创建文件时超时,请使用chkdsk检查文件系统是否存在问题。"。

可见,上述机制,实际上是用不同的Exception代替了【3】的State。

这种机制,在外层使用时:
try
{
....CreateFile( "C:\abc.txt" );
}
catch( AccessException e )
{
....//代码进入这里说明发生【没有权限错误】
}
catch( FileExistedException e )
{
....//代码进入这里说明发生【文件已经存在错误】
}
catch( TimeoutException e )
{
....//代码进入这里说明发生【超时错误】
}
对比一下【3】,其实这与【3】本质相同,只是写法不同而已。

5.综上,我个人喜欢【3】这类面向过程的写法。但很多喜欢面向对象的朋友,估计更喜欢【4】的写法。然而【3】与【4】都一样。这两种机制都是优秀的错误处理机制。

6.理论说完了,回到正题,题注问:为什么不用try catch?
答:这是因为,很多菜鸟,以及新手,他们是这样写代码的:
void CreateFile( )
//无论遇到什么错误,就抛一个 Exception,并且也不给出Msg信息。
这样的话,在外层只能使用:
try
{
....CreateFile( "C:\abc.txt" );
}
catch( Exception e )
{
....//代码进入这里说明发生错误
}
当出错后,只知道它出错了,并不知道是什么原因导致错误。这同【1】。

以及,即使CreateFile是按【4】的规则设计的,但菜鸟在外层是这样使用的:
try
{
....CreateFile( "C:\abc.txt" );
}
catch( Exception e )
{
....//代码进入这里说明发生错误
....throw Exception( "发生错误" )
}
这种情况下,如果这位菜鸟的同事,调用了这段代码,或者用户看到这个错误信息,也只能知道发生了错误,但并不清楚错误的原因。这与【1】是相同的。

出于这些原因,菜鸟的同事,以及用户,并没有想到,造成这个问题是原因菜鸟的水平太差,写代码图简单省事。他们却以为是try catch机制不行。

因此,这就导致了二逼同事,以及傻比用户,不建议用try catch。
==============================================================================
评论处有对3 跟4做比较。
知乎用户
偷懒的到处都能见着
1 年前

汤洪波
我的理解是3只能在父级做异常处理,而4是可以跨n级调用栈的。所以更推崇4。
1 年前

知乎用户
从来都只用seh,即__try __except,好处是异常时stackwalker抓调用堆栈方便
1 赞1 年前

张路
不能同意更多,目前公司的写法就是返回int,感觉总是很别扭,但又说不上哪儿别扭,看了你的答案,豁然开朗
1 年前

飞龙
3只能在父级做处理,但是父级不一定有能力处理,有可能要到上面好几级,所以要用try-catch。另外c#没有异常规约,一些菜鸟可能忘了catch,直到异常进入main还往上抛,最后程序崩掉只能是他们自己sb了。
分享到:
评论

相关推荐

    trycatch.zip

    本示例中的"trycatch.zip"文件内容就是展示了如何在Golang中模拟`try...catch`和`try...catch...finally`。 Golang的核心错误处理方式是通过返回错误值。通常,函数会返回一个错误值,如果在执行过程中遇到问题,就...

    js代码-封装try-catch函数,实现套用

    这个标题"js代码-封装try-catch函数,实现套用"意味着我们要探讨如何将`try-catch`逻辑封装到一个自定义函数中,以便在多个地方重用和管理错误处理。这有助于提高代码的可维护性和整洁性。 首先,让我们理解`try-...

    C语言异常封装 模仿try catch

    总的来说,"C异常封装"的目的是在没有内置异常处理机制的C语言中,通过编程手段提供一种类似try-catch的错误处理流程,使得代码更易于理解和维护。这个压缩包中的源码是一个很好的学习资源,可以帮助理解如何在C语言...

    前端开源库-trycatch

    ### Trycatch的背景与目的 在JavaScript中,`try...catch`语句用于捕获并处理可能出现的异常。然而,对于异步操作,传统的`try...catch`往往无法追踪到完整的调用堆栈,这给调试带来了困难。Trycatch库旨在解决这一...

    利用golang实现封装trycatch异常处理实例代码

    `trycatch`是一个自定义的异常处理结构,它试图模仿传统try-catch块的功能,通过创建一个`TryCatch`结构体来实现。下面我们将详细探讨这个结构体及其方法: 1. `TryCatch` 结构体: - `errChan`:这是一个`...

    await包装器以便在没有trycatch的情况下更容易地处理错误

    在JavaScript的异步编程中,`await`关键字用于等待一个Promise对象的结果,它通常与`async`函数一起使用。然而,直接使用`await`时,如果Promise被拒绝(即发生错误),JavaScript会抛出一个未捕获的异常,这可能会...

    Java中异常处理之try和catch代码块的使用

    当`try`块中的代码触发了一个异常,控制权会立即转移到与之关联的`catch`块。在上述例子中,如果尝试除以零(即`a = 42 / d`),`ArithmeticException`会被抛出,因为这是Java中的一个运行时错误。`catch`块紧接着`...

    C++编程异常处理中try和throw以及catch语句的用法

    如果`try`块抛出的异常与某个`catch`块的类型匹配,那么对应的处理程序就会被执行。 4. **类型匹配规则**:在C++中,`catch`块的类型匹配遵循以下规则: - 精确匹配:如果`throw`表达式中的类型与`catch`块中的...

    利用try-catch判断变量是已声明未声明还是未赋值

    `实际上会提升到函数顶部,导致不论在`try`还是`catch`块中,`v`都被声明了。 为了修正这个问题,可以使用`eval`函数来延迟变量的声明: ```javascript function f() { if (typeof(v) === 'undefined') { try { ...

    使用ADO封装类的数据库程序开发实例

    封装类应该包含适当的错误处理机制,例如使用Try-Catch块捕获异常,并提供友好的错误信息。当发生错误时,不应让程序崩溃,而是返回错误信息或记录日志。 7. 数据操作: 可以创建一个DBRecordset类封装Recordset...

    liunx 下sqlite封装读写删 程序源码

    - 使用异常处理机制,如C++的`try-catch`,捕获并处理可能出现的运行时错误。 5. **性能优化**: - 使用事务进行批量操作,减少数据库的IO次数,提高性能。`sqlite3_exec()`支持BEGIN、COMMIT和ROLLBACK命令。 -...

    utils-try-function:将函数包装在trycatch块中

    尝试功能 将函数包装在try / catch块中。安装$ npm install utils-try-function用法var wrap = require ( 'utils-try-function' ) ;包装(fcn) 将function包装在try/catch块中。 function fcn ( ) {throw new Error...

    Halcon - demo_halcon用C#封装_迈德威视_halconc#_DEMO_halconCsharp_

    《Halcon - C# 封装与迈德威视摄像头集成实战详解》 在工业自动化领域,计算机视觉技术起着至关重要的作用,其中Halcon作为一款功能强大的机器视觉软件库,广泛应用于各种图像处理任务。本文将深入探讨如何使用C#...

    使用ADO封装类的数据库程序开发实例(DOC)

    通常使用try-catch块来捕获和处理这些异常。 封装ADO类是为了简化数据库程序开发,将常见的数据库操作(如打开连接、执行SQL、处理记录集等)集成到预定义的类中,这样可以减少重复代码,提高代码的可读性和可维护...

    axios的ts二次封装+调用

    } catch (error) { // 处理错误 } } ``` 通过以上步骤,我们实现了对axios的高效利用,提高了代码质量。同时,这样的封装也有利于团队协作,降低维护成本。在项目中,可以按照需求进一步扩展,比如添加批量...

    log4cplus封装类

    1. 初始化与配置:封装类在初始化时会读取配置文件,设置Appender、Layout以及日志级别。配置文件通常采用.properties格式,可以灵活定义日志输出的路径、格式、级别等。 2. 日志级别操作:封装类会提供如debug、...

    SQLite 数据库封装类

    然而,为了确保代码的健壮性和可维护性,封装类的设计应遵循良好的编程规范,如错误处理(使用try-catch语句处理可能的异常)、资源管理(确保在操作完成后关闭Cursor和数据库连接)以及适当的注释说明。 总的来说...

Global site tag (gtag.js) - Google Analytics