根据异常自定义处理逻辑(【附】java异常处理规范)
▄︻┻┳═一『异常捕获系列』Agenda:
▄︻┻┳═一有关于异常捕获点滴,plus我也揭揭java的短
▄︻┻┳═一根据异常自定义处理逻辑(【附】java异常处理规范)
▄︻┻┳═一利用自定义异常来重构代码
我们知道,对捕捉到的异常进行处理时,可以用如下方式来分别处理。
try {
return _handle(request);
} catch (ResponseErrorException e) {
return BaseResponse.Trade_Fail("-1", e.getMessage());
} catch (ThirdPlatformException e) {
return BaseResponse.Trade_Fail("-1", e.getMessage());
} catch (Exception e) {
log.error("#H5ApiServiceImpl,业务订单号:{},异常信息:{}", request.getOrder_no(), ExceptionUtils.getStackTrace(e));
return BaseResponse.Fail("-1", "系统异常");
}
上面的ResponseErrorException和ThirdPlatformException是工程里自定义的异常类型。由于这里对这2个异常的处理逻辑相同,上面的代码用“|”运算符可重构为:
try {
return _handle(request);
} catch (ResponseErrorException | ThirdPlatformException e) {
return BaseResponse.Trade_Fail("-1", e.getMessage());
} catch (Exception e) {
log.error("#H5ApiServiceImpl,业务订单号:{},异常信息:{}", request.getOrder_no(), ExceptionUtils.getStackTrace(e));
return BaseResponse.Fail("-1", "系统异常");
}
Further more,ResponseErrorException和ThirdPlatformException派生自相同的基类PaycenterRuntimeException。那么,上面的代码也可重构为:
try {
return _handle(request);
} catch (PaycenterRuntimeException e) {
return BaseResponse.Trade_Fail("-1", e.getMessage());
} catch (Exception e) {
log.error("#H5ApiServiceImpl,业务订单号:{},异常信息:{}", request.getOrder_no(), ExceptionUtils.getStackTrace(e));
return BaseResponse.Fail("-1", "系统异常");
}
Further more,考虑到代码的简洁性和可扩展性(比如日后有了新的自定义异常),对代码做优化调整:先不分具体的异常,直接捕获所有异常的父类Exception,之后再进行实例化异常判断,做相应的结果处理。重构为:
try {
return _handle(request);
} catch (Exception e) {
if (e instanceof PaycenterRuntimeException){
return BaseResponse.Trade_Fail("-1", e.getMessage());
} else {
log.error("#H5ApiServiceImpl,业务订单号:{},异常信息:{}", request.getOrder_no(), ExceptionUtils.getStackTrace(e));
return BaseResponse.Fail("-1", "系统异常");
}
}
上面的instanceof也可以用java.lang.Class类里的isInstance来取代,不过用法是PaycenterRuntimeException.class.isInstance(e)。从代码整洁的角度看,个人认为不如直接使用instanceof。
这一脚,看似踢了别人,其实毁了自己。你以为他挡着你了,其实是他在撑着你。未来的世界,一定不属于尔虞我诈的人;而是属于善良、懂得合作、懂得感恩的人。
【附】java异常处理规范
1. 【强制】不要捕获Java类库中定义的继承自RuntimeException的运行时异常类,如:IndexOutOfBoundsException/ NullPointerException,这类异常由程序员预检查来规避,保证程序健壮性。
正例:if(obj != null) {...}
反例:try { obj.method() }catch(NullPointerException e){…}
2. 【强制】异常不要用来做流程控制,条件控制,因为异常的处理效率比条件分支低。
3. 【强制】对大段代码进行try-catch,这是不负责任的表现。catch时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的catch尽可能进行区分异常类型,再做对应的异常处理。
4. 【强制】捕获异常是为了处理它,不要捕获了却什么都不处理而抛弃之,如果不想处理它,请将该异常抛给它的调用者。最外层的业务使用者,必须处理异常,将其转化为用户可以理解的内容。
5. 【强制】有try块放到了事务代码中,catch异常后,如果需要回滚事务,一定要注意手动回滚事务。
6. 【强制】finally块必须对资源对象、流对象进行关闭,有异常也要做try-catch。
说明:如果JDK7,可以使用try-with-resources方法。
7. 【强制】不能在finally块中使用return,finally块中的return返回后方法结束执行,不会再执行try块中的return语句。
8. 【强制】捕获异常与抛异常,必须是完全匹配,或者捕获异常是抛异常的父类。就像上面的,所抛的ResponseErrorException或ThirdPlatformException是捕获的PaycenterRuntimeException的派生类。
说明:如果预期抛的是绣球,实际接到的是铅球,就会产生意外情况。
9. 【推荐】方法的返回值可以为null,不强制返回空集合,或者空对象等,必须添加注释充分说明什么情况下会返回null值。调用方需要进行null判断防止NPE问题。
说明:本规约明确防止NPE是调用者的责任。即使被调用方法返回空集合或者空对象,对调用者来说,也并非高枕无忧,必须考虑到远程调用失败,运行时异常等场景返回null的情况。
10.【推荐】防止NPE,是程序员的基本修养,注意NPE产生的场景:
- 返回类型为包装数据类型,有可能是null。
- 返回int值时注意判空。
反例:public int foo(){return Integer对象},如果为null,自动解箱抛NPE。
正例:public int foo(){if(null==Integer对象) return 0;else return Integer对象}
- 数据库的查询结果可能为null。
- 集合里的元素即使isNotEmpty,取出的数据元素也可能为null。
- 远程调用返回对象,一律要求进行NPE判断。
- 对于Session中获取的数据,建议NPE检查,避免空指针。
- 级联调用obj.getA().getB().getC();一连串调用,易产生NPE。
11.【推荐】在代码中使用“抛异常”还是“返回错误码”,对于公司外的http/api开放接口必须使用“错误码”;而应用内部推荐异常抛出;跨应用间RPC调用优先考虑使用Result方式,封装isSuccess、“错误码”、“错误简短信息”。
说明:关于RPC方法返回方式使用Result方式的理由:
1) 使用抛异常返回方式,调用方如果没有捕获到就会产生运行时错误。
2) 如果不加栈信息,只是new自定义异常,加入自己的理解的error message,对于调用端解决问题的帮助不会太多。如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输的性能损耗也是问题。
12.【推荐】定义时区分unchecked / checked 异常,避免直接使用RuntimeException抛出,更不允许抛出Exception或者Throwable,应使用有业务含义的自定义异常。 推荐业界已定义过的自定义异常,如:DaoException / ServiceException等。
13.【参考】避免出现重复的代码(Don’tRepeat Yourself),即DRY原则。
说明:随意复制和粘贴代码,必然会导致代码的重复,在以后需要修改时,需要修改所有的副本,容易遗漏。必要时抽取共性方法,或者抽象公共类,甚至是共用模块。
正例:一个类中有多个public方法,都需要进行数行相同的参数校验操作,这个时候请抽取:
private boolean checkParam(DTO dto){...}
根据异常自定义处理逻辑(【附】java异常处理规范)的更多相关文章
- java异常处理规范
异常处理的优势[存在意义]:异常检测者有检测出异常的能力,但不知道在出现该异常的情况下应该怎么处理.故库方法一般会抛出异常给调用者来处理.所以总结而言,异常处理的优势就是,将处理错误(调用者处理)从检 ...
- Java异常处理机制及两种异常的区别
java异常处理机制主要依赖于try,catch,finally,throw,throws五个关键字. try 关键字后紧跟一个花括号括起来的代码块,简称try块.同理:下面的也被称为相应的块. ...
- 如何正确使用Java异常处理机制
文章来源:leaforbook - 如何正确使用Java异常处理机制作者:士别三日 第一节 异常处理概述 第二节 Java异常处理类 2.1 Throwable 2.1.1 Throwable有五种构 ...
- 基础知识《十一》Java异常处理总结
Java异常处理总结 异常处理是程序设计中一个非常重要的方面,也是程序设计的一大难点,从C开始,你也许已经知道如何用if...else...来控制异常了,也许是自发的,然而这种控制 ...
- Java异常处理总结Exception\Error
Java异常处理总结Exception\Error 2012-12-28 08:17:17| 分类: JAVA | 标签:java |举报|字号 订阅 Java异常处理总结 ...
- java异常处理(父子异常的处理)
我当初学java异常处理的时候,对于父子异常的处理,我记得几句话“子类方法只能抛出父类方法所抛出的异常或者是其子异常,子类构造器必须要抛出父类构造器的异常或者其父异常”.那个时候还不知道子类方法为什么 ...
- 深入理解java异常处理机制
异常指不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等.异常是一个事件,它发生在程序运行期间,干扰了正常的指令流程.Java通 过API中Throwable类的众多子类描述各种不同的 ...
- Java提高篇——Java 异常处理
异常的概念 异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误java.lang.Error:如果你用Syst ...
- java异常处理机制
本文从Java异常最基本的概念.语法开始讲述了Java异常处理的基本知识,分析了Java异常体系结构,对比Spring的异常处理框 架,阐述了异常处理的基本原则.并且作者提出了自己处理一个大型应用系统 ...
随机推荐
- ubuntu16.04编译安装imu_tk
imu_tk代码地址 https://bitbucket.org/alberto_pretto/imu_tk 安装依赖项 sudo apt-get install build-essential cm ...
- Bootstrap框架 inconfont font-awesome
Bootstrap框架和inconfont.font-awesome使用 iconfont的使用:https://www.cnblogs.com/clschao/articles/10387580.h ...
- PE/ELF文件里面存的是什么呢?
malloc分配的空间是连续的吗?PE/ELF文件里面存的是什么呢?
- [development][PCRE] PCRE
概念: PCRE (Perl Compatible Regular Expressions): 与Perl兼容的正则表达式,由C实现.但也不是完全相同,与Perl的正则表达式还是略有不同. https ...
- Hash算法解决冲突的方法
https://blog.csdn.net/feinik/article/details/54974293 Hash算法解决冲突的方法一般有以下几种常用的解决方法1, 开放定址法:所谓的开放定址法就是 ...
- 抽屉之Tornado实战(2)--数据库表设计
经过我们上次分析,数据库要有最基本的四张表,用户表,消息表,类型表,点赞表,评论表,接下来我们看着怎么设计吧 首先我们要清楚,表设计的代码是写在models下的 用户表 #一张表对应一个类 class ...
- kafka相关命令
查看kafka消费组对应的信息:./kafka-consumer-groups.sh --bootstrap-server 172.17.6.10:9092 --describe --group fr ...
- c# string 扩展方法
场景:只显示一字符串的前50个字符,多余的用“...”省略号替代 如果不用扩展方法当然也可以实现,写一个静态方法,如下: public class StringUtil { /// <summa ...
- Java 用HTTP的方式发送JSON报文请求
前言: 项目调用第三方接口时,通常是用socket或者http的通讯方式发送请求:http 为短连接,客户端发送请求都需要服务器端回送响应,请求结束后,主动释放链接.Socket为长连接:通常情况下S ...
- (1.15)mysql锁问题之InnoDB锁
关键词:innodb锁,mysql锁 概要: 1.事务的隔离级别 2.InnoDB锁争用 3.innodb锁 [3.1]innodb的行锁模式及加锁方法 其实,默认情况下,mysql 的 select ...
