try catch 语句好不好?
2016-06-12 23:24
246 查看
try catch 语句好不好?
在ITOOjava5.0代码走查中,有一个 细节,Try catch 不是很建议用,如果是用了,又是为什么呢,对于这个进行
一个小的总结。
一句话解释:
try catch机制可以非常好。觉得try catch 不是很好的,可能是还没有发现她的好!
二、详细解释:
1.程序要健壮,必须要设计报错机制。
最古老,也是最常见的,比如:
//如果创建文件失败就返回false,否则返回true。
这种报错方式,显然不好。因为它没有给出产生错误的具体原因。
2.改进:一个函数或过程,会因为不同的原因产生错误,报错机制必须要把这些错误原因进行区分后,再汇报。
比如:
这样看上去,比【1】要好些,至少指出了比较具体的失败原因,但是,还不够。
3.很多情况下,函数需要把详细的原因,用字符串的方式,返回:
4.我个人推崇上面这种方式,完整,美观。但是这种流程,容易与正常的代码混在一起,不好区分开。因此,Java、C#等设计了try catch这一种特殊的方式:
可见,上述机制,实际上是用不同的Exception代替了【3】的State。
这种机制,在外层使用时:
5.综上,我个人喜欢【3】这类面向过程的写法。但很多喜欢面向对象的朋友,估计更喜欢【4】的写法。然而
【3】与【4】都一样。这两种机制都是优秀的错误处理机制。
6.理论说完了,回到正题,题注问:为什么不用try catch?
解答:这是因为,有的人可能还不是很熟练,以及新手,他们可能这样写代码的:
当出错后,只知道它出错了,并不知道是什么原因导致错误。这同【1】。
以及,即使CreateFile是按【4】的规则设计的,但菜鸟在外层是这样使用的:
这种情况下,调用了这段代码,或者用户看到这个错误信息,也只能知道发生了错误,但并不清楚错误的原因。这
与【1】是相同的。
出于这些原因,可能新手以及用户,并没有想到,造成这个问题原因是熟练度不够,写代码图简单省事。他们却以
为是try catch机制不行。
所以,在这种情况下,肯定很多人觉得,还是不建议用try catch。
最好问清楚是那种语言。不同语言处理Try Catch的机制不一样,所以也会有不同回答。
上面增加额外的cost, 这个额外的cost不是说只有throw exception的时候才会有,而是在try catch block里面的每一行
代码中都会有,这也是为什么他不建议你使用try catch最主要的原因。在Windows的源代码中,是没有任何try catch
的,全部用HResult来处理。
cost可以忽略不计,但是如果真的在代码运行过程中throw exception了,这个cost还是很大的。所以,在C#代码设计
中,throw exception基本上是你认为不会发生这种意外的情况下,否则,如果是常见错误,最好不要throw
exception。
比如Java, try catch也是建议使用的,我这个用的不熟,不过看它的说明,即使是throw exception的时候的cost也
很小。
这里《Effective Java》的有关异常的几个条目说的非常明白.建议题主去看一下.我这里就简单的搬运一下.部分原
文如下:
只针对不正常的情况才使用异常书中给出了一个例子
这是一个非常明显的错误,希望通过异常来中断循环而达到某种优化.其实不然.
•JVM对异常的块中的代码几乎不做优化.
•而且创建、抛出、捕获异常都是十分昂贵的
•正常的遍历数组并不会造成冗余的边界检查,现代的JVM会做出优化
避免不必要的使用被检查的异常
“被检查的异常”是Java语言的一个很好的特性。与返回代码不同,"被检查的异常"会强迫程序员处理例外的条
件,大大提高了程序的可靠性。
但是,过分使用被检查异常会使API用起来非常不方便。如果一个方法抛出一个或多个被检查的异常,那么调用
该方法的代码则必须在一个或多个catch语句块中处理这些异常,或者必须通过throws声明抛出这些异常。 无论是通
过catch处理,还是通过throws声明抛出,都给程序员添加了不可忽略的负担。
适用于"被检查的异常"必须同时满足两个条件:第一,即使正确使用API并不能阻止异常条件的发生。第二,一旦
产生了异常,使用API的程序员可以采取有用的动作对程序进行处理。
不要忽略异常,有些程序员会写出下面的代码
空的catch块会使异常达不到应有的目的,异常的目的是强迫你处理不正常的条件。忽略一个异常,就如同忽略一
个火警信号一样 -- 若把火警信号器关闭了,那么当真正的火灾发生时,就没有人看到火警信号了。所以,至少catch
块应该包含一条说明,用来解释为什么忽略这个异常是合适的。
从它设计的角度就是为了处理一些意料不到的情况,但是因为当初引入的时候各种各样的原因,导致有些语言为了性
能,不推荐使用。
BTW, try catch最好不要catch (Exception), 这样会吃掉不该吃的问题,比如C#中的StackOverflowException,
OutOfMemoryException, NullReferenceException etc. 该crash的时候就应该让App crash, restart, 这也是保护你
service的一个好方法。
在ITOOjava5.0代码走查中,有一个 细节,Try catch 不是很建议用,如果是用了,又是为什么呢,对于这个进行
一个小的总结。
一句话解释:
try catch机制可以非常好。觉得try catch 不是很好的,可能是还没有发现她的好!
二、详细解释:
1.程序要健壮,必须要设计报错机制。
最古老,也是最常见的,比如:
bool CreateFile( ); //如果创建文件失败就返回false,否则返回true。
//如果创建文件失败就返回false,否则返回true。
这种报错方式,显然不好。因为它没有给出产生错误的具体原因。
2.改进:一个函数或过程,会因为不同的原因产生错误,报错机制必须要把这些错误原因进行区分后,再汇报。
比如:
<span style="font-size:18px;">int CreateFile(): //如果创建成功就返回1. //如果是因为没有权限,导致失败,返回-1。 //如果是因为文件已经存在,导致失败,返回-2。 //如果是因为创建文件发生超时,导致失败,返回-3。</span>
这样看上去,比【1】要好些,至少指出了比较具体的失败原因,但是,还不够。
3.很多情况下,函数需要把详细的原因,用字符串的方式,返回:
<span style="font-size:18px;">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检查文件系统是否存在问题。"。</span>
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?
解答:这是因为,有的人可能还不是很熟练,以及新手,他们可能这样写代码的:
<span style="font-size:18px;">void CreateFile( ) //无论遇到什么错误,就抛一个 Exception,并且也不给出Msg信息。 这样的话,在外层只能使用: try { ....CreateFile( "C:\abc.txt" ); } catch( Exception e ) { ....//代码进入这里说明发生错误 }</span>
当出错后,只知道它出错了,并不知道是什么原因导致错误。这同【1】。
以及,即使CreateFile是按【4】的规则设计的,但菜鸟在外层是这样使用的:
<span style="font-size:18px;">try { ....CreateFile( "C:\abc.txt" ); } catch( Exception e ) { ....//代码进入这里说明发生错误 ....throw Exception( "发生错误" ) }</span>
这种情况下,调用了这段代码,或者用户看到这个错误信息,也只能知道发生了错误,但并不清楚错误的原因。这
与【1】是相同的。
出于这些原因,可能新手以及用户,并没有想到,造成这个问题原因是熟练度不够,写代码图简单省事。他们却以
为是try catch机制不行。
所以,在这种情况下,肯定很多人觉得,还是不建议用try catch。
二 、经验总结:
最好问清楚是那种语言。不同语言处理Try Catch的机制不一样,所以也会有不同回答。(1)对于C++:
是不推荐用try catch的,它推荐使用Windows API那种HResult来返回错误情况,原因是try catch会在已有的代码上面增加额外的cost, 这个额外的cost不是说只有throw exception的时候才会有,而是在try catch block里面的每一行
代码中都会有,这也是为什么他不建议你使用try catch最主要的原因。在Windows的源代码中,是没有任何try catch
的,全部用HResult来处理。
(2)对于C#:
try catch是建议使用的,C#设计的时候吸取的C++ try catch的教训,所以直接用Try catch包裹已有代码增加的cost可以忽略不计,但是如果真的在代码运行过程中throw exception了,这个cost还是很大的。所以,在C#代码设计
中,throw exception基本上是你认为不会发生这种意外的情况下,否则,如果是常见错误,最好不要throw
exception。
比如Java, try catch也是建议使用的,我这个用的不熟,不过看它的说明,即使是throw exception的时候的cost也
很小。
三、在java语言中:
其实通过上面的例子我们发现,不是不建议用.而是不应该滥用.这里《Effective Java》的有关异常的几个条目说的非常明白.建议题主去看一下.我这里就简单的搬运一下.部分原
文如下:
只针对不正常的情况才使用异常书中给出了一个例子
try { int i=0; while (true) { arr[i]=0; i++; } } catch (IndexOutOfBoundsException e) { }
这是一个非常明显的错误,希望通过异常来中断循环而达到某种优化.其实不然.
•JVM对异常的块中的代码几乎不做优化.
•而且创建、抛出、捕获异常都是十分昂贵的
•正常的遍历数组并不会造成冗余的边界检查,现代的JVM会做出优化
避免不必要的使用被检查的异常
“被检查的异常”是Java语言的一个很好的特性。与返回代码不同,"被检查的异常"会强迫程序员处理例外的条
件,大大提高了程序的可靠性。
但是,过分使用被检查异常会使API用起来非常不方便。如果一个方法抛出一个或多个被检查的异常,那么调用
该方法的代码则必须在一个或多个catch语句块中处理这些异常,或者必须通过throws声明抛出这些异常。 无论是通
过catch处理,还是通过throws声明抛出,都给程序员添加了不可忽略的负担。
适用于"被检查的异常"必须同时满足两个条件:第一,即使正确使用API并不能阻止异常条件的发生。第二,一旦
产生了异常,使用API的程序员可以采取有用的动作对程序进行处理。
不要忽略异常,有些程序员会写出下面的代码
<span style="font-size:24px;">try { ... } catch (SomeException e) { } </span>
空的catch块会使异常达不到应有的目的,异常的目的是强迫你处理不正常的条件。忽略一个异常,就如同忽略一
个火警信号一样 -- 若把火警信号器关闭了,那么当真正的火灾发生时,就没有人看到火警信号了。所以,至少catch
块应该包含一条说明,用来解释为什么忽略这个异常是合适的。
小结:
try catch是否建议使用要看具体语言,最重要衡量的标准就是它对已有的代码性能有多大的影响。但是从它设计的角度就是为了处理一些意料不到的情况,但是因为当初引入的时候各种各样的原因,导致有些语言为了性
能,不推荐使用。
BTW, try catch最好不要catch (Exception), 这样会吃掉不该吃的问题,比如C#中的StackOverflowException,
OutOfMemoryException, NullReferenceException etc. 该crash的时候就应该让App crash, restart, 这也是保护你
service的一个好方法。
相关文章推荐
- 离暑假还有一个月
- Spring学习(二十二) Bean配置的三种方式(XML、注解、Java类)介绍与对比
- [leetcode72]Edit Distance(dp)
- Strut2+convention+json返回(maven)
- ZLYD团队第5周项目总结
- Android 数据库的事务
- 22.python中的面向对象和类的基本语法
- Tomcat探秘(5):tomcat关闭过程详述
- Running Android apps using Docker and ARC Welder
- c语言学习笔记25之指针1
- 对java set集合的理解与学习
- Java Instrument (五) Agent attach
- Lightoj 1009
- SQL限定查询
- SQL Server常用管理命令
- 第三课、key的操作
- [Android]使用BeanShell实现Android简易科学计算器
- 【Linux】tar指令用法
- 王爽《汇编语言》第十一章 实验十一 题目解答
- border:1px #F00 solid;