`
accphc
  • 浏览: 125749 次
  • 性别: Icon_minigender_1
  • 来自: CD
社区版块
存档分类
最新评论

老掉牙的话题,java的异常处理。

阅读更多

关于系统中的异常怎么处理,之前也看过很多的文章。只是觉得越看越糊涂,大家持很多不同的意见。

现在想形成一套自己的观点,合自己口味的解决方案。没有对与不对,因人而宜。

 

DataAccessException extends RuntimeException  Dao层异常

ServiceException extends RuntimeException   Service层异常

我被java的RuntimeException和Exception的使用一直弄得头晕。
现在的观点是,把Exception转化成RuntimeException,省的方法还throws,个人觉得的throws看起来不爽,呵呵。
这就相当于在自己写代码过程中放弃了使用Exception。减少烦恼

但是有些自己写的工具类当中又是怎么处理呢。抛还是不抛(通过返回值),抛什么?

 

欢迎大家发表下意见,批评改正。

 

分享到:
评论
68 楼 pufan 2011-03-19  
carlkkx 写道
pufan 写道
carlkkx 写道
在Swing/Awt编程环境中,设计方法抛出IOException意味着这是一个耗时操作,编写EDT安全程序就会相对容易很多:不catch编译器会提示你,强迫你使用SwingWorker等其他手段。桌面程序中所有与IO相关甚至耗时的计算方法抛出IOException已经是一个最佳实践了。
————————————————————————
我是用Swing开发过还算比较大的软件的,居然一个方法是否耗时需要IOException来表征,这不得不说是一个悲哀。


看来你开发的还不够大。请问如果在EDT线程内,你怎么能够快速得知并且受到编译器提示一个方法调用(可能封装了其他的方法)会是一个耗时操作,恰恰checked exception的层层抛出机制可以轻松保证这一点。

我真是晕了,我使用某个方法都不知道这个方法可能的执行时间?如果我要和server通信那么显然时间可能比较长,这些这么显然的事情需要一个异常来表征?而且不见得IO就是慢的,就一定不能在EDT里面承受,如果我简单读一个配置文件,那么速度很快完全可以放在EDT里面而不需要另外的线程。难道你不觉得通过IOException来判断是这件事很可笑吗?

首先,你调用的方法很可能不是你写的,如果你不阅读api doc或看源码的话,很可能“使用某个方法都不知道这个方法可能的执行时间”。另外在程序中层层封装的情况太常见了,特别是大型程序,不利用checked exception层层抛出的机制忽略耗时操作的事情很容易发生。

至于读取本地文件也要看你读多大的,还包括xml解析时间,一般情况下这些也要放到EDT线程外执行的。即使你放到EDT内部,那也是checked exception给你了这个一个条件让你判断耗时是否小。
67 楼 carlkkx 2011-03-19  
而且GUI程序,如果我点一下按钮,发现卡了半天,难道你这还不知道慢?而且不问青红皂白看到IOException就要构建后台线程,这本根就是增加复杂性,我们首先当然希望直接在EDT里面就能搞定,只有确实慢了我们才考虑后台线程。
66 楼 carlkkx 2011-03-19  
pufan 写道
carlkkx 写道
在Swing/Awt编程环境中,设计方法抛出IOException意味着这是一个耗时操作,编写EDT安全程序就会相对容易很多:不catch编译器会提示你,强迫你使用SwingWorker等其他手段。桌面程序中所有与IO相关甚至耗时的计算方法抛出IOException已经是一个最佳实践了。
————————————————————————
我是用Swing开发过还算比较大的软件的,居然一个方法是否耗时需要IOException来表征,这不得不说是一个悲哀。


看来你开发的还不够大。请问如果在EDT线程内,你怎么能够快速得知并且受到编译器提示一个方法调用(可能封装了其他的方法)会是一个耗时操作,恰恰checked exception的层层抛出机制可以轻松保证这一点。

我真是晕了,我使用某个方法都不知道这个方法可能的执行时间?如果我要和server通信那么显然时间可能比较长,这些这么显然的事情需要一个异常来表征?而且不见得IO就是慢的,就一定不能在EDT里面承受,如果我简单读一个配置文件,那么速度很快完全可以放在EDT里面而不需要另外的线程。难道你不觉得通过IOException来判断是这件事很可笑吗?
65 楼 pufan 2011-03-19  
carlkkx 写道
利用Checked Exception做业务流程分支设计比用返回值个人感觉更优雅
——————————————————————
晕倒,这已经是完全滥用异常了,程序执行的正常结果也用异常来表征了,如果我是调用者碰到这样的API我应该是难受死还哪来的优雅。

不要一棒子打死,异常是否可以反映业务流分支这正应该不用争论了。很多情况下调用者的范围或者调用后程序的行为是可以预知和限定的,程序是死的,人是活的,不要太绝对。
64 楼 pufan 2011-03-19  
carlkkx 写道
在Swing/Awt编程环境中,设计方法抛出IOException意味着这是一个耗时操作,编写EDT安全程序就会相对容易很多:不catch编译器会提示你,强迫你使用SwingWorker等其他手段。桌面程序中所有与IO相关甚至耗时的计算方法抛出IOException已经是一个最佳实践了。
————————————————————————
我是用Swing开发过还算比较大的软件的,居然一个方法是否耗时需要IOException来表征,这不得不说是一个悲哀。


看来你开发的还不够大。请问如果在EDT线程内,你怎么能够快速得知并且受到编译器提示一个方法调用(可能封装了其他的方法)会是一个耗时操作,恰恰checked exception的层层抛出机制可以轻松保证这一点。
63 楼 carlkkx 2011-03-19  
即使一个程序员非常了解异常的意义,也会被checkedException弄得烦死,不得不用RuntimeException包装它,很多开源库就是这么做的。这就是当初这些API设计者在异常上武断的决定导致的,自以为把调用方想透了,其实不过是自以为是而已。
62 楼 carlkkx 2011-03-19  
异常处理的选择权永远在使用方,被使用方不能越俎代庖,被使用方的职责就是要么完成目标要么报告错误,除此以外不要多管闲事。
61 楼 carlkkx 2011-03-19  
在同等程序员水平的情况下,我刚说的反向测试完善法也比checkedException带来的乱吞状况好很多。而且写程序的时候轻松程度不一样。
60 楼 carlkkx 2011-03-19  
比如读取一个默认的配置文件,如果配置文件不存在就生成一个默认的.这种完全是应该调用者处理的,而且他有能力处理的,这种就应该抛出checkedException,
————————————————————
即使你如此的信誓旦旦,这种假设也只是你抛出异常一方的一厢情愿,尤其是你的模块公用性越强那么就越不能自以为是了。也许有些设置就是必须要设置的呢?即使不是,也许不是它直接调用方能处理的呢?

这里有个关键理念不知道你认同不认同:
你的模块就是完成定义的目标,如果完成不了就报告错误,至于错误报告之后的事是不是不应该多管闲事?
如果你认同这个理念,那么checkedException就是错误的设计。
59 楼 carlkkx 2011-03-19  
qianhd 写道
carlkkx 写道
ppgunjack 写道
当a库依赖b库,你调用a库,如果b库全是RuntimeException,并且你拿不到b库文档,你用a库能写出健壮的代码是不可能的,你自己精心构建的异常处理逻辑能轻松被无法预见的RuntimeException打断,因为你预计不到a库什么时候会被b库的雷给牵连,任何对a的调用都要考虑可能由b导致的连环雷
把代码比作做事,RuntimeException就相当于天灾人祸,意外之外的,至于发生了你愿意自己继续干还是终止取决于你自己意愿
而checked就是说你需要弄清楚并且汇报给上级那些是问题,那些是你会遇到但你解决不了的,但都是你意识到的问题,别人让你做事,你要给别人说好,如果让我干可能出现意外1,2,3,怎么处理你自己决定

调用链是a->b->c->d,如果d是没任何这种提前约定的契约,那么a要操心的就是调用b的所有接口,b随时也有可能被c的调用打断,而c随时会被d打断,看似编码简单,实际异常处理被大幅扩大

最简单的例子,你老板让你干活都需要先分析风险,你可能会让底下再分析,然后汇报,然后才是每层自己根据汇报的风险制定计划和执行

如果全unchecked相当于你没任何汇报,只是告诉上级,你让我干事有风险,干什么事都有风险也可能都没风险,你分配我任务的时候自己看着办,还有我下属的风险我可能也转给你也可能不给你我自己搞定,这看我自己风格,你也自己看着办吧

你只跟a有关系,如果a的描述中没有那是a的问题,照你这么说你做每一件事都是寻根问底,否则就不存在安全性了,那封装就没有意义了,因为每一层API你都要看到底,否则你心中没有底。


我觉得 你说来说去 就2个问题
1.使用checkedException会导致乱吞异常
2.不乱吞异常就强制throws会导致接口丑陋

你的建议是 全部RuntimeException 然后在方法注释中写明会抛出什么样的异常


这里面有些奇怪的逻辑
首先 乱吞异常的肯定是213的程序员,既然是213那他会注意调用方法的注释吗? 或者他会写清楚他的注释吗?

其次 有些异常以后的操作是统一的,比如数据库回滚,这些完全不需要调用者干预,这种异常就应该定义成RuntimeException,但是,比如读取一个默认的配置文件,如果配置文件不存在就生成一个默认的.这种完全是应该调用者处理的,而且他有能力处理的,这种就应该抛出checkedException,强制他去处理.免得他忘记了.


你这里忽略一个非常重要的问题,乱吞异常严重性比不处理还要严重,在系统的顶层设置一个未处理异常捕获器,如果有异常到这里,可以提示以及退出系统等。但如果乱吞的话,程序可能已经无法达到预期效果了,但是却没有任何错误报告。这使得系统处于最不友好的状态。
我现在假设一个系统所有的人都没考虑处理任何异常,全部只按正常流程写,即使某些地方确实需要捕获并且处理的,那么经过几次迭代测试之后很多被顶层未处理异常捕获的异常就去查那一个层本来要处理的却没有处理,通过这种方式系统逐步改进也会比充满了乱吞异常代码的系统好很多,因为异常能够报告出来比埋了的好很多。而且我举得是极端例子。不过在
没有很多checkedException扰乱视听下代码会写的很轻松,即使非常一般的程序员犯错误的机会反而小,事后通过多次迭代测试把系统的可靠性逐步完善起来。在各个线程的顶部都要有未处理异常捕获器,要保证系统不能无声无息崩溃。当然如果虚拟机或操作系统崩溃了那自然是另当别论。
58 楼 qianhd 2011-03-19  
carlkkx 写道
ppgunjack 写道
当a库依赖b库,你调用a库,如果b库全是RuntimeException,并且你拿不到b库文档,你用a库能写出健壮的代码是不可能的,你自己精心构建的异常处理逻辑能轻松被无法预见的RuntimeException打断,因为你预计不到a库什么时候会被b库的雷给牵连,任何对a的调用都要考虑可能由b导致的连环雷
把代码比作做事,RuntimeException就相当于天灾人祸,意外之外的,至于发生了你愿意自己继续干还是终止取决于你自己意愿
而checked就是说你需要弄清楚并且汇报给上级那些是问题,那些是你会遇到但你解决不了的,但都是你意识到的问题,别人让你做事,你要给别人说好,如果让我干可能出现意外1,2,3,怎么处理你自己决定

调用链是a->b->c->d,如果d是没任何这种提前约定的契约,那么a要操心的就是调用b的所有接口,b随时也有可能被c的调用打断,而c随时会被d打断,看似编码简单,实际异常处理被大幅扩大

最简单的例子,你老板让你干活都需要先分析风险,你可能会让底下再分析,然后汇报,然后才是每层自己根据汇报的风险制定计划和执行

如果全unchecked相当于你没任何汇报,只是告诉上级,你让我干事有风险,干什么事都有风险也可能都没风险,你分配我任务的时候自己看着办,还有我下属的风险我可能也转给你也可能不给你我自己搞定,这看我自己风格,你也自己看着办吧

你只跟a有关系,如果a的描述中没有那是a的问题,照你这么说你做每一件事都是寻根问底,否则就不存在安全性了,那封装就没有意义了,因为每一层API你都要看到底,否则你心中没有底。


我觉得 你说来说去 就2个问题
1.使用checkedException会导致乱吞异常
2.不乱吞异常就强制throws会导致接口丑陋

你的建议是 全部RuntimeException 然后在方法注释中写明会抛出什么样的异常


这里面有些奇怪的逻辑
首先 乱吞异常的肯定是213的程序员,既然是213那他会注意调用方法的注释吗? 或者他会写清楚他的注释吗?

其次 有些异常以后的操作是统一的,比如数据库回滚,这些完全不需要调用者干预,这种异常就应该定义成RuntimeException,但是,比如读取一个默认的配置文件,如果配置文件不存在就生成一个默认的.这种完全是应该调用者处理的,而且他有能力处理的,这种就应该抛出checkedException,强制他去处理.免得他忘记了.

57 楼 fandayrockworld 2011-03-19  
碰到让强制try catch的,就throw new RuntimeException(e);
个人观点:
如果不是特定的Exception(自定义的业务中的Exception),尽量不要直接throw出来。
56 楼 carlkkx 2011-03-19  
ppgunjack 写道
有checked你可以默认所有没异常申明的函数都是ok的,除了那些申明自己要抛的不用太关心那些没申明的
你使用api是不可能每个都去看文档的
我原来之所以会在dao采取这种方式因为我认为每个dao函数都应该有抛异常的可能,用check的话上层调用写起来太罗嗦,尤其再加个接口,实际spring的dao也是这样处理
而实际普遍考虑,大部分api是不应该我们操心问题的,如果有异常声明,则我们只用关注这些少量的问题点
如果全部都runtime那我们就要考虑每个调用可能造成的中断,每个api我都要参考它的文档关于异常的描述
另外一旦调用链拉长,a->d的文档是不会都那么全面和可靠,因为抛异常的可能性会随链的长度相乘

大多复杂性就是通过分而治之解决的,你非要担心你所面临的API以外的东西,那有什么办法呢?这样担心那就有太多担心了,这样的话,集成电路OK不OK那也是担心的。
55 楼 carlkkx 2011-03-19  
什么是异常?如果我正确完成任务,这个正确完成的结果表示断不会用异常表示,只有不能正确完成任务我才抛出异常表示我无法达到目的。
54 楼 carlkkx 2011-03-19  
利用Checked Exception做业务流程分支设计比用返回值个人感觉更优雅
——————————————————————
晕倒,这已经是完全滥用异常了,程序执行的正常结果也用异常来表征了,如果我是调用者碰到这样的API我应该是难受死还哪来的优雅。
53 楼 carlkkx 2011-03-19  
在Swing/Awt编程环境中,设计方法抛出IOException意味着这是一个耗时操作,编写EDT安全程序就会相对容易很多:不catch编译器会提示你,强迫你使用SwingWorker等其他手段。桌面程序中所有与IO相关甚至耗时的计算方法抛出IOException已经是一个最佳实践了。
————————————————————————
我是用Swing开发过还算比较大的软件的,居然一个方法是否耗时需要IOException来表征,这不得不说是一个悲哀。
52 楼 piao_bo_yi 2011-03-19  
pufan 写道
carlkkx 写道
我认为关于Checked exceptions 已经尘埃落定,结论就是:Checked exceptions是失败的设计。C#放弃这个不是没有道理的。


曾经我也是这样认为,但现在。。。

举两个例子:
在Swing/Awt编程环境中,设计方法抛出IOException意味着这是一个耗时操作,编写EDT安全程序就会相对容易很多:不catch编译器会提示你,强迫你使用SwingWorker等其他手段。桌面程序中所有与IO相关甚至耗时的计算方法抛出IOException已经是一个最佳实践了。

利用Checked Exception做业务流程分支设计比用返回值个人感觉更优雅:编译器会帮你把所有可能分支条件处理好,多一条不行少一条也不行,用返回值的话很可能会有遗漏,对方法使用者不友好。


这正是carlkkx反对的原因。
51 楼 pufan 2011-03-19  
carlkkx 写道
我认为关于Checked exceptions 已经尘埃落定,结论就是:Checked exceptions是失败的设计。C#放弃这个不是没有道理的。


曾经我也是这样认为,但现在。。。

举两个例子:
在Swing/Awt编程环境中,设计方法抛出IOException意味着这是一个耗时操作,编写EDT安全程序就会相对容易很多:不catch编译器会提示你,强迫你使用SwingWorker等其他手段。桌面程序中所有与IO相关甚至耗时的计算方法抛出IOException已经是一个最佳实践了。

利用Checked Exception做业务流程分支设计比用返回值个人感觉更优雅:编译器会帮你把所有可能分支条件处理好,多一条不行少一条也不行,用返回值的话很可能会有遗漏,对方法使用者不友好。

50 楼 ppgunjack 2011-03-18  
有checked你可以默认所有没异常申明的函数都是ok的,除了那些申明自己要抛的不用太关心那些没申明的
你使用api是不可能每个都去看文档的
我原来之所以会在dao采取这种方式因为我认为每个dao函数都应该有抛异常的可能,用check的话上层调用写起来太罗嗦,尤其再加个接口,实际spring的dao也是这样处理
而实际普遍考虑,大部分api是不应该我们操心问题的,如果有异常声明,则我们只用关注这些少量的问题点
如果全部都runtime那我们就要考虑每个调用可能造成的中断,每个api我都要参考它的文档关于异常的描述
另外一旦调用链拉长,a->d的文档是不会都那么全面和可靠,因为抛异常的可能性会随链的长度相乘
49 楼 magneu 2011-03-18  
异常的出现就是因为入力的条件不符合要求, 不能正确为客户返回正确的结果。 造成这种现象的原因是无法从编译程度上限制 入力条件完全满足自己的需求。

个人觉得Runtime exception和check exception的区别是。
check exception: 程序级不可控的异常,是因为终端用户的原因或者物理环境的原因导致的。 所以这些异常要一层层往上抛, 最终发给终端用户。  这样处理的目的是为了给上层的调用者忽略异常的机会。 告诉调用者你发给我的这些条件, 可能存在这样的问题, 如果出现这样的问题, 需要你处理一下。
Runtime exception: 程序级可控的异常。 这些基本和终端用户没啥关系。 基本是因为程序员编码失误造成的。 所以直接抛出运行时异常,终止系统运行。 (当然真正运用的时候,会在用户最初始的调用方法的地方捕获所有的异常,不会真正让系统挂掉)。

所以,个人感觉对于异常设计的初衷是(自己想的): 对于用户的错误, 那么需要用户去检查, 所以一层层抛出,最终抛给用户。
而对于运行时异常, 则直接挂掉整个系统, 让程序员来重新修改系统。

相关推荐

    JavaReport-V3-Enterprise-Released.rar

    前几天要搞一个老掉牙的SSH项目,缺少了这个插件。全网去找,好不容易找到。放到WEB-INF/lib目录,发现不会自动引入,手动引入后,调用java report的程序不报错,但服务器出现放频繁出现it is not java class的错误...

    JAVA经典算法各种排序算法

    老掉牙 河內塔 費式數列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 騎士走棋盤 八個皇后 八枚銀幣 生命遊戲 字串核對 雙色、三色河內塔 背包問題(Knapsack Problem) 數、運算 蒙地...

    第二期:RIP高级,老掉牙的协议?其实没想象的那么简单.pptx

    RIP高级,老掉牙的协议?其实没想象的那么简单,资深华为讲师为你讲解rip协议

    JavaReport-V3-Enterprise-Released.jar

    前几天要搞一个老掉牙的SSH项目,缺少了这个插件。全网去找,好不容易找到。放到WEB-INF/lib目录,发现不会自动引入,手动引入后,调用java report的程序不报错,但服务器出现放频繁出现it is not java class的错误...

    pascal语言教程,老掉牙了,不过很不好找

    尽管它在现代编程中可能显得“老掉牙”,但Pascal在计算机科学教育领域曾扮演着重要的角色,对后来的编程语言如C、C++和Java产生了深远影响。这个“古董”教程可能对初学者或历史爱好者具有一定的价值。 Pascal的...

    老掉牙的lynx for win32

    尽管"老掉牙的lynx for win32"这个标题暗示这是一款较旧的版本,对于那些需要在Windows环境下运行命令行浏览器或者进行网页抓取、自动化任务的人来说,Lynx仍然是一个有用的工具。 Lynx的主要特点和优势在于: 1. *...

    C和JAVA经典算法.rar

    老掉牙 河內塔 費式數列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 騎士走棋盤 八個皇后 八枚銀幣 生命遊戲 字串核對 雙色、三色河內塔 背包問題(Knapsack Problem) 數、運算 蒙地...

    Java和C语言实现各种经典算法(含代码图例)

    老掉牙 河内塔 费式数列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 骑士走棋盘 八个皇后 八枚银币 生命游戏 字串核对 双色、三色河内塔 背包问题(Knapsack Problem) 数、运算 蒙地...

    c语言经典算法包括老掉牙,汉诺塔,三色旗

    老掉牙 河内塔 巴式数列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 骑士走棋盘 八个皇后 八枚银币 生命游戏 字串核对 双色、三色河内塔 背包问题(Knapsack Problem) 数、运算 蒙地卡罗法...

    一个老掉牙的故事作文.doc

    这篇文档实际上是一个关于亲情和爱情的故事,虽然标题和描述中没有明确的IT相关知识点,但从故事中我们可以引申出一些普遍的人生智慧和情感理解,这些也是人们在IT行业中经常需要处理的情感层面: 1. **习惯与依赖...

    老掉牙的问题:二叉树的遍历

    二叉树的三种遍历的递归和非递归方法,语言种类,C++,如果有不足的地方,请与作者联系,谢谢。

    SmaliInjector20170719

    dex2jar 的步骤使用的是 google 自家的 enjarify 工具,没使用老掉牙的、对部分混淆apk处理极不准确极不稳定的 dex2jar(d2j) 5). jar2dex 使用的是 android studio 自带的 dx.bat 工具,貌似 dex2jar(d2j) 在做jar...

    ACM经典算法 代码+详解

    老掉牙 河內塔 費式數列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 騎士走棋盤 八個皇后 八枚銀幣 生命遊戲 字串核對 雙色、三色河內塔 背包問題(Knapsack Problem) 數、運算 蒙地...

    Delphi Cmdshell 线程注入、文件释放程序

    内容索引:Delphi源码,系统相关,线程注入 这是个老掉牙的话题了,运行后AVP狂报,NOD32没反应,不过策略简直太牛了,主要实现了线程注入、文件释放、添加自启等一些常规手段来表现,作者是锦屏中学初二(10)班 王臻,...

    C语言经典算法大全.pdf

    老掉牙 河内塔 费式数列 巴斯卡三角形 三色棋 老鼠走迷官(一) 老鼠走迷官(二) 骑士走棋盘 八个皇后 八枚银币 生命游戏 字串核对 双色 三色河内塔 背包问题(Knapsack Problem) 数 运算 蒙地卡...

    LunchtimeBoredom:我在整个大三的午餐时间编写的代码。 常规编程问题和一些有趣的东西。 新项目即将推出新的存储库!

    随时为项目提出建议,解决同类问题很快就会老掉牙。 另外,这个神秘的“ GUI”是什么意思? 控制台文本是必经之路! 注意:maze.txt文件与SearchAlgorithms.java一起使用。 它只是一个示例文件,可以更改,但是...

    sdl推箱子源码和资源.zip_SDL游戏源码_sdl 游戏_sdl游戏_推箱子

    这个压缩包包含了一个基本的游戏实现,但描述中提到是“一个老掉牙的小小小游戏,只是半个成品”,意味着这可能是一个早期版本或未完成的项目。 在标签中,“sdl游戏源码”、“sdl_游戏”和“sdl游戏”都是与SDL...

    计算机组成实验

    不必再去实验室,用那些老掉牙的实验箱了。直接用它去做实验吧!

Global site tag (gtag.js) - Google Analytics