根据异常自定义处理逻辑(【附】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的异常处理框 架,阐述了异常处理的基本原则.并且作者提出了自己处理一个大型应用系统 ...
随机推荐
- [No0000145]深入浅出图解C#堆与栈 C# Heap(ing) VS Stack(ing)理解堆与栈2/4
前言 虽然在.Net Framework 中我们不必考虑内在管理和垃圾回收(GC),但是为了优化应用程序性能我们始终需要了解内存管理和垃圾回收(GC).另外,了解内存管理可以帮助我们理解在每一个程 ...
- HTML5:一些部件
在表单里经常会用到很多部件 <!DOCTYPE html> <html lang="en"> <head> <meta charset=& ...
- 于dm-0 dm-1
dm是device mapper的意思,dm-0, dm-1的实体可以通过下面几个命令看出,lvm会把每个lv连接到一个/dev/dm-x的设备档,这个设备档并不是一个真正的磁盘,所以不会有分区表存在 ...
- invariant theory 不变量理论
https://baike.baidu.com/item/不变量理论/9224903?fr=aladdininvariant theory 一组几何元素由 k个参数组成的向量 P1表示.若 T为某一变 ...
- Page8:对偶原理以及结构分解[Linear System Theory]
内容包含状态转移矩阵的对偶性.方块图的对偶性.时序的对偶性以及对偶性原理,能控能观标准型及其结构分解
- 根据Request获取客户端IP
转自: http://www.cnblogs.com/icerainsoft/p/3584532.html http://www.cnblogs.com/bingya/articles/3134227 ...
- 洛谷P3233 世界树 [HNOI2014] 虚树
正解:虚树 解题报告: 传送门! 首先看到这种就要想到虚树这个是毫无疑问的QwQ 建虚树什么的都可以循规蹈矩地做,不说辣,具体可以看下虚树学习笔记什么的看下板子 但是建好虚树之后怎么搞还是有点儿讲究, ...
- python面向对象的三大特性
一.继承 面向对象中的继承就是继承的类直接拥有被继承类的属性而不需要在自己的类体中重新再写一遍,其中被继承的类叫做父类.基类,继承的类叫做派生类.子类.在python3中如果不指定继承哪个类,默认就会 ...
- JDBC的简单封装
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import ...
- 前端路由实现(history)
HTML5 history 新增了两个 API:history.pushState 和 history.replaceState 两个 API 都接收三个参数: 1.状态对象(state object ...