回忆java来时路-第五章 正常地处理异常
来源:互联网 发布:psdto3d软件免费下载 编辑:程序博客网 时间:2024/04/27 19:24
1)丑陋的try-catch段落
回想自己代码中大概有几分之一的篇幅来对付异常?是否到处充满try,catch片段?曾经为了处理sql查询的语句是这样:
import java.sql.*;
public class JDBCExample {
public static void main(String[] args) {
Connection conn = null; try{
//准备sql,执行查询
sql = "SELECT id, first, last, age FROM Employees”;
ResultSet rs = stmt.executeQuery(sql);
//其它业务逻辑,返回这个rs里的业务数据
rs.close();stmt.close();
conn.close();
}catch(SQLException se){
se.printStackTrace(); }catch(Exception e){
e.printStackTrace(); }finally{
try{if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}
}
}
}
一个很简单的查询方法,真正有用的主体代码只有寥寥3、4行,而写try,catch相关的代码就占了14行。这样的代码,毫无美感可言,我相信没有几个人喜欢,这也是起初我们对处理异常充满厌恶的罪魁祸首。正常的做法应该把这些重复的机械式代码用一个模版封装好,程序员只关心最主要的逻辑代码,后续的由模版方法里统一编写。当然现在的开发者不会有这样的烦恼,因为后来的orm工具和spring给我们提供了比较友好的template模版来处理这些烦人的重复代码。尽管sql查询垂直领域有第三方工具给我们通用解决方案,然而那些我们系统里的类似异常处理,还得要我们程序员自己写一个template模版来处理相关调用。具体的template写法可以参考spring的jdbctemplate试试,这里就不详解了。
2) 为了防止NPE,我们准备了多少if判断语句?
我们被告知每个方法里的第一步就是对方法参数做非空的检查。否则NPE必然如影随行。问题是有时候我们的方法参数是一个复合对象,这个方法本身可能只需编写几行运算代码。如果对参数对象进行非空检查,还要深度递归对这个参数对象的属性也做非空判断(不要笑,真的大型复杂业务中就这样的,例如复合订单对象),这样一来又会出现一个方法的主体代码只有几行,而写非空判断代码占据大部分篇幅。由于一般程序员不会真的对一个参数对象里的所有属性都写一遍非空判断,只选择那些认为重要的属性检查,实际运行时经常还会出现因为忘记检验某些属性而导致NPE错误,这样的教训数不胜数。一个成熟稳定的系统都是通过时间积累下来哪些非空检查是否足够了,新上线的系统会时不时出现这样的问题。
对于这个烦恼,我自己是这样认为的:
a) 如果调用方是给外部系统调用,或者虽然是系统内调用,但不受我们自己控制的代码,那么确实要必须尽可能的做非空校验。每当一个方法里的非空参数检查确实看不过去时,说明我们要对这个方法重构,用另外的方法来代替它。如果恰好你碰到的是维护了好几年的旧系统,你就只能捏着鼻子忍受,或者冒着风险去改造,风险和收益成正比,如果你改好了,同事和领导会另眼看你,如果搞渣了就自己背黑锅吧:)。
b) 如果是由我们自己写的方法调用的,那么就可以把这个检查前置到参数产生的地方,正常它是经过了业务逻辑处理分支才运行到你的方法里。我们方法对参数的约束,也是基于前置业务逻辑处理的结果,如果在我们方法里抛出了NPE,说明我们在调用这个方法之前的业务逻辑代码存在着某个漏洞,此时该修复的是这个前置漏洞,而不是在我们的方法里再增加一个非空判断,后者的修改仅仅是为了不抛出导致程序中断的NPE,实际的业务逻辑错误并没有解决掉。那么哪些是我们自己可控的方法,我可以给出一个最少范围的判断标准,那就是所有private的方法,它仅限于当前类中使用,那么没必要在这个方法体里做非空检查,而应该在调用这个方法的前置逻辑中做好正常逻辑修复,使之不至于出现null值传给该private方法。这是我个人的一点体会。
c) 容易忽略的return null,在有返回值的方法中,很多时候大家都return null,其实它也是导致后续一堆非空判断的原因之一,如果我们都用return 一个空对象来代替,就会减少我们程序的NPE,同时也减少非空判断的麻烦。不要小看这点,道理很简单,也不难做,但实际上像阿里这样的大公司中能做到的都不到十分之一。
3)异常的其它
有关异常还有很多重要的讨论,想必大家也都了解,就不再赘述,effective java 和很多大师的书上解释了异常的正确处理方式,比如不要用异常来当作逻辑分支的条件;在碰到真正程序无法继续处理的情况时才抛出异常等。
0 0
- 回忆java来时路-第五章 正常地处理异常
- 回忆java来时路-第二章 对象之外
- 回忆java来时路-第七章 类的初始化
- 回忆java来时路-第三章 谈谈java相关的书籍
- 回忆java来时路-第四章 接口还是抽象类
- 回忆java来时路-第六章 集合类的演进
- 回忆java来时路-第一章 关于那个美好的梦:“一次编写,到处运行”
- 第五章 java 异常 处理
- 第五章 异常错误处理
- java 第五次课-异常处理
- [第五章、异常处理] 第一节、异常处理基础
- 【Oracle强化】⑤第五章 异常处理
- 第五章 try块和异常处理
- Java day08 异常处理与正常代码分离 图形面积
- 来时路
- 《Java 解惑》 第五章 异常之谜
- Linux私房菜第五章要点回忆
- 0704第五讲异常处理
- FreeMarker与Jsp的区别
- 推荐系统评价指标
- 冒泡排序
- SPOJ375 Query on a tree
- MQTT协议知识分享(一)
- 回忆java来时路-第五章 正常地处理异常
- iOS10 因为各种权限而出现的崩溃的问题
- 利用fastjson和反射实现为VO属性赋值
- 《机器学习&&深度学习》 视频课程资源百度云下载
- FS注销一个在线账户
- Android之隐式意图(Intent)如何查找匹配的组件
- (七)1 时间管理与内核延时
- 利用Caffe做回归(regression)
- ART世界探险(19) - 优化编译器的编译流程