附加:自定义异常,继承Exception和RuntimeException的区别;(本篇是转载博客,慎看)

说明:

(1)为什么写这篇博客?:在【Spring Boot电商项目23:商品分类模块二:【增加目录分类】接口;】中;出于【我们在方法内部throw抛出ImoocMallException异常时,,,,不用再,在,方法后面throws 这个异常】的目的,让ImoocMallException异常改继承了RuntimeException;这样以后,【当我们在方法内部throw抛出ImoocMallException异常时,,其就会自动帮我们把这个异常,给throws抛上去】;

而,自己对这个点,是有点迷糊的;所以,就有了这篇博客;

(2)本篇博客参考了一个知乎问答【Java自定义异常,应该继承Exception还是Runtime Exception,为什么?】;

(3)声明:对于本篇博客的内容,自己并没有十分理解;所以,本篇博客并没有作出结论性的总结;

1.第一个回答;该回答的作者是【二大王】;

继承Exception还是继承RuntimeException是由异常本身的特点决定的,而不是由是否是自定义的异常决定的。

例如我要写一个java api,这个api中会调用一个极其操蛋的远端服务,这个远端服务经常超时和不可用。所以我决定以抛出自定义异常的形式向所有调用这个api的开发人员周知这一操蛋的现实,让他们在调用这个api时务必考虑到远端服务不可用时应该执行的补偿逻辑(比如尝试调用另一个api)。此时自定义的异常类就应继承Exception,这样其他开发人员在调用这个api时就会收到编译器大大的红色报错:【你没处理这个异常!】,强迫他们处理。

又如,我要写另一个api,这个api会访问一个非常非常稳定的远端服务,除非有人把远端服务的机房炸了,否则这个服务不会出现不可用的情况。而且即便万一这种情况发生了,api的调用者除了记录和提示错误之外也没有别的事情好做。但出于某种不可描述的蛋疼原因,我还是决定要定义一个异常对象描述“机房被炸”这一情况,那么此时定义的异常类就应继承RuntimeException,因为我的api的调用者们没必要了解这一细微的细节,把这一异常交给统一的异常处理层去处理就好了。


个人理解:(对于这条回答,自己理解的还不够……)

          ● 有一个前提:当我们抛出了自定义异常时,都是需要处理的;

             即,比如Service层抛的自定义异常,我们都是需要把这个异常向上抛的;Controller收到这个自定义异常后,也都是需要包装成对应的API统一返回对象,以告知给调用者的;

          ● 但是,对于有的自定义异常,其影响不是特别大;当真的出现了这个自定义异常,我们去处理就行了,没什么大不了的;

             于是,对于这种自定义异常,我们建议继承RuntimeException;此时,当我们抛这种自定义异常时,我们抛就行了,程序会自动帮我继续向上抛,帮我们处理;

          ● 但是,对于有的自定义异常,如果我们遇到了,需要告知调用者,调用者得知道,这儿可能抛出自定义异常;以便让调用者知道这个情况后,调用者主动、手动去决定应该怎么应对这个异常;

 2.第二个回答;该回答的作者是【某知乎用户】;

直接看规范吧

Chapter 11. Exceptions

Exception is the superclass of all the exceptions from which ordinary programs may wish to recover.

The class RuntimeException is a direct subclass of Exception. RuntimeException is the superclass of all the exceptions which may be thrown for many reasons during expression evaluation, but from which recovery may still be possible.

RuntimeException and all its subclasses are, collectively, the run-time exception classes.

The unchecked exception classes are the run-time exception classes and the error classes.

The checked exception classes are all exception classes other than the unchecked exception classes. That is, the checked exception classes are Throwable and all its subclasses other than RuntimeException and its subclasses and Error and its subclasses.

规范里说明了,Java Exception分为两种, unchecked exceptionchecked exception 显然,前者是运行时异常继承自RuntimeException,后者受控异常继承自Exception。

我理解面试官考察的基本就是这些,至于自定义异常到底继承哪个,完全系统/业务所然,通常业务类异常如果希望它是Throwable的,或者带有业务语义的异常,就定义checked;系统类异常就unchecked。当然,这也不是原则...


个人理解:(对于这条回答,自己的理解,同样还不够……)

一个重要疑问:系统异常都是Java官方写好的吧,其要继承Exception 还是RuntimeException,是我们能决定的?

 3.第三个回答,作者是【陈硕】(PS:这是个大佬);该回答直接建议:对于自定义异常,继承RuntimeException;

 4.第四个回答,作者是【luckalway】;(这个回答和【第二个回答】结合者看,似乎更有收获)

其实两者很好区分,但绝大部分的开发人员都知道选用哪种!在异常的规范里已经描写清楚,如果这个异常发生,用户自己能够有法解决,那就用checked exception。我打个比方:用户发现在转账的时候发现余额不足,或者在转账的时候对方账户已经销户,这时候就应该定义两个不同的checked exception。CoinNotEnoughException&AccountNotExistException。当第一个异常发生的时候,用户就知道余额不够,先充足够钱再进行转账,CoinNotEnoughException根据业务需要可以带一些属性,比如当前余额是多少。第二个业务场景自己想象。有的人会说,这些不是事先判断吗,当然会事先判断,但不在同一个事物里任何可能都有发生。

RuntimeException直白讲就是系统异常,或者系统出错了。或程序有Bug,或环境有问题。比如空指针,SQL语法错误,数据库连不上,用户对这些异常是无能为力的,碰到这类异常系统统一处理-就告诉用户:系统出现异常了,请报告给管理员....。这类异常一出现,一定要LOG记录下来,维护人员要第一时间就要去解决的,所以异常要带足够的信息,比如数据访问不了,数据库的名称、host、端口号都log打印出来。调用WS出错的,就要把当时的URL、参数、http method也打印出来。最好是log里一看就知道哪里出问题了。

所以选用哪种异常,取决于终端用户碰到这个异常会怎么处理。

 5.第五个回答,作者是【张皓不是张浩】;

对抛出的异常,checked exception要与方法耦合,尤其是接口中定义的方法影响比较大,使用起来不够灵活。不抛出异常,就得满屏的try-catch。

我现在的做法是除非抛出的异常需要调用层显式处理,否则自定义异常都继承RuntimeException,在最上层的调用统一做一次try-catch。这样一来方法的声明和使用简洁了很多。

其实,我觉得最重要的还是团队的约定。、


PS:这种做法,也是自己目前比较接收的做法:自定义异常继承RuntimeException异常;这样以后,底层抛出的异常,会一致汇聚到最上层(如Controller),然后最上层收到异常后,再做处理;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值