try catch 语句好不好?
在ITOOjava5.0代码走查中,有一个 细节,Try catch 不是很建议用,如果是用了,又是为什么呢,对于这个进行
一个小的总结。
一句话解释:
try catch机制可以非常好。觉得try catch 不是很好的,可能是还没有发现她的好!
bool CreateFile( ); //如果创建文件失败就返回false,否则返回true。
<span style="font-size:18px;">int CreateFile(): //如果创建成功就返回1. //如果是因为没有权限,导致失败,返回-1。 //如果是因为文件已经存在,导致失败,返回-2。 //如果是因为创建文件发生超时,导致失败,返回-3。</span>
<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>
void CreateFile() //如果创建成功就不会抛出异常。 //如果是因为没有权限,导致失败,会抛出AccessException,这个Exception的Msg属性为"用户【guest】没有权限在【C:\】这个目录下创建该文件。建议您向管理员申请权限,或者更换具有权限的用户。"。 //如果是因为文件已经存在,导致失败,会抛出FileExistedException,这个Exception的Msg属性为"文件【C:\abc.txt】已经存在。如果需要覆盖,请添加参数:arg_overwrite = true"。 //如果是因为创建文件发生超时,导致失败,会抛出TimeoutException,这个Exception的Msg属性为"在创建文件时超时,请使用chkdsk检查文件系统是否存在问题。"。
try { ....CreateFile( "C:\abc.txt" ); } catch( AccessException e ) { ....//代码进入这里说明发生【没有权限错误】 } catch( FileExistedException e ) { ....//代码进入这里说明发生【文件已经存在错误】 } catch( TimeoutException e ) { ....//代码进入这里说明发生【超时错误】 } 对比一下【3】,其实这与【3】本质相同,只是写法不同而已。
5.综上,我个人喜欢【3】这类面向过程的写法。但很多喜欢面向对象的朋友,估计更喜欢【4】的写法。然而
【3】与【4】都一样。这两种机制都是优秀的错误处理机制。
解答:这是因为,有的人可能还不是很熟练,以及新手,他们可能这样写代码的:
<span style="font-size:18px;">void CreateFile( ) //无论遇到什么错误,就抛一个 Exception,并且也不给出Msg信息。 这样的话,在外层只能使用: try { ....CreateFile( "C:\abc.txt" ); } catch( Exception e ) { ....//代码进入这里说明发生错误 }</span>
<span style="font-size:18px;">try { ....CreateFile( "C:\abc.txt" ); } catch( Exception e ) { ....//代码进入这里说明发生错误 ....throw Exception( "发生错误" ) }</span>
这种情况下,调用了这段代码,或者用户看到这个错误信息,也只能知道发生了错误,但并不清楚错误的原因。这
与【1】是相同的。
出于这些原因,可能新手以及用户,并没有想到,造成这个问题原因是熟练度不够,写代码图简单省事。他们却以
为是try catch机制不行。
是不推荐用try catch的,它推荐使用Windows API那种HResult来返回错误情况,原因是try catch会在已有的代码
上面增加额外的cost, 这个额外的cost不是说只有throw exception的时候才会有,而是在try catch block里面的每一行
代码中都会有,这也是为什么他不建议你使用try catch最主要的原因。在Windows的源代码中,是没有任何try catch
的,全部用HResult来处理。
try catch是建议使用的,C#设计的时候吸取的C++ try catch的教训,所以直接用Try catch包裹已有代码增加的
cost可以忽略不计,但是如果真的在代码运行过程中throw exception了,这个cost还是很大的。所以,在C#代码设计
中,throw exception基本上是你认为不会发生这种意外的情况下,否则,如果是常见错误,最好不要throw
exception。
比如Java, try catch也是建议使用的,我这个用的不熟,不过看它的说明,即使是throw exception的时候的cost也
很小。
这里《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的一个好方法。