分享
 
 
 

JAVA中异常使用范围的一些思考

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

在这个开源框架大放异彩的时代,人们往往非常关注架构本身引入的各种新理念,而其异常处理机制常常被忽视。事实上,一个框架的异常处理方式是维持其稳定的基础。而且一个应用程序框架本身对异常的处理方式,也会对其使用者处理异常的方式造成深刻的影响。本文参考了一些大师对JAVA中异常使用方式的论述,并提出了几条简单的见解,作为抛砖引玉之作,请大家共同探讨。

在JAVA中,异常实际上可以看作是方法的非正常返回值。例如 User getUser(String usrName)这个方法,本来应该返回一个用户对象,但是当异常出现时,方法并没有返回User,而是返回了一个Exception。这个非正常情况下的返回值就是异常。

本着异常就是方法的非正常返回值这种思想,可以对以下几个问题进行探讨:

1. 什么时候应该使用(自定义)异常

2. 应该使用已检查异常(CheckedException,我认为如果翻译为可控异常更加恰当),还是运行时异常(RuntimeException)。

什么时候应该使用异常:

关于自定义异常使用的时机,有一种传播的较为普遍的说法:异常只能用于处理“真正的异常情况”,不能参与流程控制,因为过多使用异常会造成性能的损失,因此在我们的系统中,应该尽量少使用自定义异常。

首先让我们考察一下什么是“真正的异常”。

一般情况下人们认为在操作系统一级(准确地说是JDK一级)抛出的异常就是“真正的异常”。然而所谓“系统级异常”和“应用级异常”在很多时候很难界定。例如对于一个文字处理软件来说,“NoEnoughSpaceException”这个异常究竟是系统级的,还是应用级的?从系统的角度来看,磁盘空间不够,应属于系统级异常。但从应用的角度看,文件无法保存了,也是应用级异常。因此我认为这种分类方法从分类学角度来说是不科学的:所谓“系统级”和“应用级”的范围经常会互相覆盖。

另外一种较注重实效的看法是,从方法的功能角度看,决定是否应该使用异常。结合前面的“异常事实上是一种特殊返回值”的说法,举例如下:

User getUser(String usrName) ,使用者期望得到User对象,但是如果真的有特殊情况发生,而使用者又没有进行事先判断,那么我们只能抛出异常。在这里可能抛出的异常是一个自定义的异常:“用户不存在”。

boolean isUserExist(String usrName) ,使用者是在判断用户是否存在,所以我们当然没有必要抛出“用户不存在”异常,只需返回一个布尔值即可。

void registUser(String usrName),这个方法没有返回值,因此如果出现了异常情况,只能抛出异常。这里可能抛出的异常有“用户名已用”、“系统禁止注册”等。

我认为第二种使用异常的方法是较科学且较直观的:一切从实效出发。在这种做法的指导下,我们可能会在系统中使用大量自定义异常。

有人认为异常不应该参与流程控制,并将这种参与流程控制的异常讽刺为“SuperIf”。关于此问题我们可以参考RUP中关于异常事件流的论述, RUP的结论是“异常情况是现实中客观存在的一类事件,当我们必须对它进行处理时,这个处理就发生在异常流中”。因此在JAVA中将异常作为一种流程控制手段,和RUP的异常流概念不谋而合,且对异常的处理就可以在异常块中进行。

有人可能害怕大量使用异常会带来性能上的损失。性能问题是另外一个需要庞大篇幅论证的问题,大家可以参考Rod Johnson在他的《J2EE Without EJB》一书中对性能优化的分析。简而言之是一句话:一切语言级优化所作的努力,在一次I/O或者数据库读写操作中将化为乌有。因此对异常使用带来的小小性能损失,实在是不需“言必性能”。

使用已检查异常还是运行时异常:

这个问题的争议较大,比较极端的如

Bruce Eckel和Anders Hejlsberg,认为应该取消一切CheckedException,以带有自定义消息的RuntimeException替代之,

Bruce甚至亲自给出一段代码告诉大家如何将CheckedException转为RuntimeException。而James Gosling则使用CheckedException过了火,有人讽刺James:在他的眼里,用户都是上帝,有能力且必须处理诸如“IOException”这类谁也没有办法的事情。Rod Johnson比较中庸,他认为CheckedException有其有用之处:类似James Gosling说的,当用户必须对某种特殊情形作出反应的时候,我们可以使用CheckedException来提醒用户“这种情形可能会发生,你要对它进行处理”。

但是Rod极大的缩小了这种情形发生的范围,他认为只有当异常流必须被特殊处理的时候,才有使用CheckedException的需求。举例来说,int registUser(String usrName)方法用于注册用户。这个API的作者规定,当返回值为0时,代表注册成功;返回值为1,代表用户名已用;返回值为2,代表系统禁止注册…… 在这种情况下,就应该使用CheckedException,而不是RuntimeException或简单返回值。因为除了0的每个返回值都代表了一条异常流,且每个异常流都要进行特殊处理,比如用户名已有时,我们可能要自动转入一个提醒页面,提醒用户其他可用的用户名;禁止注册时,我们要进入一个公告页面,这个页面展示了禁止注册的原因及开放时间等等。

对上面的情况,可以做一个更精确的总结:只有当异常参与了流程控制时,才应该使用CheckedException。

那么我们如何判断异常是否应该参与流程控制?这种判断可以从需求入手。如果需求要求我们,在这条异常流上,要进行A处理,在那条异常流,要进行B处理,则很明显,这里应该使用CheckedException来控制流程。如果需求只是“如果发生了异常,在界面上进行提示”,那么这种情况下,我们就没有必要使用CheckedException,只要使用带有消息的RuntimeException即可。

使用CheckedException有一个显著的问题,因为每个使用者都必须对方法法抛出的CheckedException作出响应,因此一旦方法已经被广泛使用,要添加一个新的CheckedException就变得十分困难:每个使用者都要做出相应的修改。但是从另一个角度看,如果你添加CheckedException的理由确实是“需求要求如此,我们必须对它进行特殊处理”,则每个方法的使用者就应该增加一个新的catch,并增加这种新的特殊处理。

这个问题也提醒我们,使用CheckedException时,一定要确定是否这种情况需要“特殊处理”,否则尽量以RuntimeException进行代替。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有