异常处理遇到过的那些坑 | 架构栈
![](https://img.haomeiwen.com/i5981964/be15366439a02900.png)
今年有个目标之一就是提升团队代码的质量,所以时常会思索如何把这件事做到更好,不想教条主义,也不想搞出一个代码规范,强制团队照着做,落地的效果不好,反而把大家的积极性给弄没了。所以我的原则是,我们一起看看什么事是我们不能做的,排除掉,剩下的就是我们可以做的,同时真正搞清楚问题在哪里,而不是简单的模仿。从我个人的经验看,代码优化中最重要的一点就是对异常情况的处理。今天,我就借这个话题,谈谈如何来优化我们的代码。
坑1:捕捉异常不做处理
如下段代码所示,不知道各位在自家的代码中见过多少,我是期望大家不要遇见。且不说printStackTrace()这样的代码就不应该出线在正式的上线代码中,不做处理本身这会导致业务的潜在问题被隐藏了,所以这个坑是我认为异常处理中最糟糕的一点。
try
{
....
}
catch(Exception ex)
{
ex.printStackTrace();
System.out.println(XXX);
}
对于异常的捕捉处理,遵循以下的流程:
处理该异常,执行具体的逻辑处理,加上必要的系统日志记录 (log4j,logcat ...)。
涉及其他系统或者上一级系统,需要转换成对应的消息通知相关系统。上一级是前端,需要转换成前端可以“读懂”的错误提示。
无法处理该异常或者该异常需要上一级统一处理,Throw out该异常。
坑2:不处理资源释放
还是见代码说话,如果append出错,那么IO流就不会被关掉,那么最终就会导致整个程序因为溢出崩掉。
FileWriter fileWriter = null;
try
{
fileWriter = new FileWriter("");
fileWriter.append(item.toString());
fileWriter.close();
}
catch (IOException e)
{
...
}
在使用文件、IO流、数据库连接等不会自动释放的资源时,应该在使用完毕后马上将其关闭。关闭资源的代码try...catch...finally的finally内执行,否则就可能因为Exception的原因造成资源无法释放。
坑3:对异常不进行分类处理
代码中,最容易看到的一种情况就是设定catch的异常类型是Exception, 并且只有一套处理逻辑, 如下:
try{
...
}
catch (Exception e){
...
}
这里的问题主要有以下两点:
1. catch的不同Exception,可能需要执行不同的处理逻辑,一个catch要同时处理所有逻辑就很难实现。
2. 由于是捕捉的基类Exception, 那么RuntimeException也会被捕捉到,如果稍微不注意的话,RuntimeException最终没有任何实际处理,代码中的真正错误被掩盖掉了。
所以,正确的做法应该是按照具体的异常进行分类处理, 例如:
try{
...
}
catch (FileNotFoundException e){
// alert that the specified file
// does not exist
}
catch (EOFException e){
// alert that the end of the file
// was reached
}
catch (ObjectStreamException e){
// alert that the file is corrupted
}
catch (IOException e){
// alert that some other I/O
// error occurred
}
坑4:将大段代码放进一个Try-Catch中
有时可以看到,一些代码的作者恨不得把整个函数里的实现代码都放入单个try中,原因就在于为了图省事,不愿花时间分析一大块代码中哪几行代码会抛出什么异常、异常的具体类型是什么,应该如何处理。这样的做法导致异常发生后,后续调试找问题更麻烦,一大段代码中有太多的地方可能抛出Exception。这样的做法导致,很难去统计和判断要catch哪一些类型的Exception, 只能写一个粗糙的Exception, 又掉进我们说的第3个坑里。
一点总结
在和大家一起分析了上面的异常坑后,如果未来我们想避免踩进一个异常坑,编写异常代码可以遵循以下三个点:
1. 出了什么错?
2. 在哪出的错?
3. 为什么出错?
更多文章,请手动搜索微信公众号【架构栈】: ForestNotes