该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2004-02-19
muziq 写道 Anders举的例子其实很可笑的,他说底层方法抛出4个异常,随着梯子越来越高,你的方法大概需要声明40个异常,其实他一定没有写过Java程序,更没有设计过Java方法,异常只需要对本层方法的调用者有意义,调用者根本就不需要关心底层错误的细节,那方法干吗还要声明那些底层抛的异常呢?一定是自己在方法里面消化掉了嘛!(需要调用者作为错误处理的异常合并抛一个异常) 我想你可能没有完全理解Anders的意思,我们程序中处理异常的时候,大致有两种方式:可能大多数都是在各自的程序中分别处理异常,这样会造成异常处理代码很分散。更好的方式应该是把这些异常处理代码统一在一个地方(class, model)来处理。对于前一种情况,当然不太可能发生像Anders说的那样情况,但会使异常处理代码分散于各处,对代码可读性,可维护性都会造成很大的影响。对于后一种情况, 系统越复杂,那要处理的异常恐怕就真的会像梯子一样越来越高了。即使你每层写个异常处理模块(class),那要处理的异常也不会太少。 这只是我的看法,其实我也并不完全赞同Anders的观点。 |
|
返回顶楼 | |
发表时间:2004-02-20
lameychen 写道 我想你可能没有完全理解Anders的意思,我们程序中处理异常的时候,大致有两种方式:可能大多数都是在各自的程序中分别处理异常,这样会造成异常处理代码很分散。更好的方式应该是把这些异常处理代码统一在一个地方(class, model)来处理。对于前一种情况,当然不太可能发生像Anders说的那样情况,但会使异常处理代码分散于各处,对代码可读性,可维护性都会造成很大的影响。对于后一种情况, 系统越复杂,那要处理的异常恐怕就真的会像梯子一样越来越高了。即使你每层写个异常处理模块(class),那要处理的异常也不会太少。 这只是我的看法,其实我也并不完全赞同Anders的观点。
我想分层处理异常是最佳的方案(除非你的系统没什么层次),系统合理地分层之后,就不会出现跨层调用的情况,这样,从方法提供者的角度看,本层抛出的异常仅对调用者有意义,另一方面,从方法调用者的角度看,本层不需要考虑下、下一层的异常,层和层之间接口的语义是很明确的。 举个例子说,你用了Hibernate以后,Hibernate封装了JDBC操作,就不需要你去捕捉SQLException这样的底层异常,Hibernate的接口按照其语义重新定义了自己的异常,而不会让SQLException“漏”出来。所以,Java的异常机制好就好在你可以准确的表达语义,可以定义更友好、易读的接口。 |
|
返回顶楼 | |
发表时间:2004-02-20
我不同意robin,exception不是异常程序流,这种东西最适合用 "契约 "参见 Eiffel. exception 属于适合处理不可预测的,可预测的不要用exception,过多的定义exception也会降低速度,因为填充 stacktrace 及其消耗资源.
|
|
返回顶楼 | |
发表时间:2004-02-26
同意potian的观点,说得不错。
|
|
返回顶楼 | |
发表时间:2004-03-10
这是从Think in Java摘的关于性能的说明
运算 示例 标准时间 本地赋值 i=n; 1.0 实例赋值 this.i=n; 1.2 int增值 i++; 1.5 byte增值 b++; 2.0 short增值 s++; 2.0 float增值 f++; 2.0 double增值 d++; 2.0 空循环 while(true) n++; 2.0 三元表达式 (x<0) ?-x : x 2.2 算术调用 Math.abs(x); 2.5 数组赋值 a[0] = n; 2.7 long增值 l++; 3.5 方法调用 funct(); 5.9 throw或catch异常 try{ throw e; }或catch(e){} 320 同步方法调用 synchMehod(); 570 新建对象 new Object(); 980 新建数组 new int[10]; 3100 Exception 需花费320的消耗,因此不同意robbin的看法.而我倾向于使用 boolean login() 全部的问题在login里就处理完毕,包括业务流程与异常。调用方只需考虑登录是否成功 |
|
返回顶楼 | |
发表时间:2004-03-10
引用 Exception 需花费320的消耗,因此不同意robbin的看法.而我倾向于使用
我不这么认为。光看系统的消耗就否定一些应该使用的系统应用异常太武断了。就拿login()这个方法来说,如果要返回的是一个User的对象,那么就有使用错误用户名和密码错误的必要。你也可以说是业务流程,但对于Login()返回user对象这个方法来说这是异常。 当然,不能滥用checkedException,这样会带来很大的性能问题。我们考虑问题不能只从一个方面考虑,使用checkedException还是有很多好处的。 |
|
返回顶楼 | |
发表时间:2004-03-10
flosed 写道 我不同意robin,exception不是异常程序流,这种东西最适合用 "契约 "参见 Eiffel. exception 属于适合处理不可预测的,可预测的不要用exception,过多的定义exception也会降低速度,因为填充 stacktrace 及其消耗资源.
这恰恰错了,eiffel里面也是需要exception的contract仅仅是一种检查机制替代不了exception.从OO的角度来看,check exception对于函数签名和接口签名是一个非常重要的事情,没有check exception接口和函数的签名语义上就不完整。 C#从实用的角度来说也没有错,只不过两者说的都不是同一件事情。C#整个设计思路就是怎么方便怎么设计,它才不管什么标准好用是第一位的。从这个角度来说Java很多地方都作的不够好,例如没有值类型,没有using等等。至于系统消耗么,这个方面就不用考虑了,看看new要多少,exception要多少.我们能够容忍到处使用的new,却不能容忍使用频率低的多的exception这便是怪事了。 很大程度上,由于我们能力有限,我们对语言的讨论基本是处于信仰上的问题。很多争论并不触及到语言的实质问题。如果真认为自己有能力从语言层面上来说问题,可以到这里来。www.allaboutprogram.com这里最近就发生过一场关于RAII和exception的争论。 |
|
返回顶楼 | |
发表时间:2004-03-11
找几句名人名言引用一下:
引用 在优化方面,我们应该遵守两条原则:
规则1:不要做优化。 规则2(仅针对专家):还是不要做优化--也就是说,在你还没有绝对清晰的优化方案之前,请不要做优化。 还有: 引用 努力编写好的程序而不是快的程序
引用 为获得好的性能而对API进行曲改,这是一个非常不好的想法。
这些话出自《Effective Java》,把它从柜子里翻出来再看看吧。 《Effective Java》里还有很多关于Exception的经典论断,非常非常值得学习,所以大家在继续争论之前请一定先看看这本书。 如果Java的世界里有真理存在,《Effective Java》就是一本阐述这些真理的圣经! |
|
返回顶楼 | |
发表时间:2004-03-13
我觉得全部应该抛出checked异常.因为我写一个类的时候,我怎么知道这个类的用户有没有能力处理我抛出的异常.即使SQLException也不一定客户就不能处理,即使一个UserExistException也不一定客户就能够处理.
我只管抛出checked exception,至于他catch不catch,catch了怎么处理,那不是我应该关心的事情. 即使这个项目里我很清楚我这个类的客户是什么样的,我也无法预计我这个类将来会被不会被用在其他地方,所以应该把决定权交给客户 |
|
返回顶楼 | |
发表时间:2004-03-15
1、异常有两种,一种是源于程序员的疏忽,一种是源于不可控的外力。有些程序员将其混为一谈,然后统一的在catch里忽略掉这种异常,是对自己的“放纵”。
2、需要捕捉的异常也有两种,一种是自己的程序抛出的,一种是系统抛出的。系统抛出的异常,没办法,必须一一处理好,但是自己的程序抛出的异常,不应该搞出复杂的异常继承体系出来,只需在异常中填入统一格式的Error Code,然后所有的程序,都统一catch这种异常,然后一律交给某个错误处理对象。而不是在自己的程序里,散布着各种各样的catch。 3、我们要追求的是程序的功能,而不是纯粹意义上的美感。 |
|
返回顶楼 | |