JAVA异常的处理注意点

举报
jping 发表于 2020/12/28 11:54:55 2020/12/28
【摘要】 Java异常处理的场景非常普遍,好的处理方式不仅可以提升代码可读性,还能帮助问题定位,接口调用更方便等等

1.  catch块不要为空来忽略异常,并且要正确打印异常信息

错误:

try {

    xxxxxx

} catch(Exception e) {

}

       捕获异常,却不做处理,屏蔽了异常的所有信息,出现异常时所有人感知不到,但是该处的代码或者调用该代码的相关功能都会出现问题,在排查问题是让人无从下手,没有达到预期的效果。对于不用逻辑处理的异常,至少添加一个日志打印,毕竟这是一种异常场景,是有问题才会出现的场景,需要把相关日志打印出来,便于排查问题出现的原因进而修复问题。

       注意打印异常信息时不要使用e.printStackTrace();,建议直接使用代码日志框架,printStackTrace()默认使用了System.err输出流进行输出,与System.out是两个不同的输出流,会导致打印出的堆栈日志跟正常输出或者业务代码执行日志交错在一起,导致日志混乱影响日志分析。并且该异常还会打印到控制台,产生错误堆栈字符串到字符串池内存空间,异常信息过多就会导致内存被占满,服务异常。

       打印异常日志时一定要把异常本身的信息打印出来,不然出现异常时任然无法准确定位。

正确:

 try {

    xxxxxx

} catch (xxxException e) {

    log.info("异常出现了!!!!!!" e. getMessage());

}

 

2.  建议不要直接捕获受检异常的基类Exception

       首先,捕获异常就是为了处理异常,不同的异常需要有不同的处理方式,区分并捕获具体的异常,就可以对具体的异常做出最准确的处理,并且对应的异常信息也是最准确的,直接捕获Exception有时会导致真实出现的异常信息模糊。

错误:

catch(Exception exception)  {

}

 

正确:

catch(ParseException | IOException exception)  {

}

 

3.  RuntimeException不应该去捕获处理

       RuntimeException,也就是运行时异常,表示代码本身存在BUG,比如ArrayIndexOutOfBoundsException,数组下标越界,数组定义的长度不够实际使用,代码若不调BUG进行处理肯定还会报错,控制台一旦报RuntimeException,不是try-catch就能解决的。这种可控的异常场景应该在编码的时候识别出来进行处理。

错误:

try {

    obj.method();

} catch(NullPointerException e){

    log.error(e,getMessage());

}

 

正确:

if (obj != null) {

    obj.method();

}

 

4.  注意try-catch 作用域

       不是所有代码都需要进行try-catch的,不能每个方法中都直接整个try-catch,大段代码的try-catch会影响代码的可读性,也会增大异常出现的场景定位难度,catch 时请分清稳定代码和非稳定代码,稳定代码指的是无论如何不会出错的代码。对于非稳定代码的 catch 尽可能进行区分异常类型,再做对应的异常处理。

错误:

try {

    xxxxxx

} catch(xxxException e){

   log.error(e.getMeaage())

}

 

正确:

xxxxxx

try {

    xxxxxx

} catch(xxxException e){

    log.error(e.getMeaage())

}

 

5.  一个方法不应抛出超过5个异常,并在Javadoc@throws标签中记录每个抛出的异常及其条件

       方法抛出过多的异常,会增加客户端异常处理的工作,让方法调用方花费大量时间去处理这些异常,并且一个方法出现过多的异常说明该方法涉及的场景很多,说明这个方法应该还需要分解不能耦合在一起。在Javadoc@throws标签中记录每个抛出的异常及其条件,可以让调用方更好的了解该方法的异常场景。

6.   使用finally关闭流资源,JDK7之后推荐使用try-with-resources

       如果有对IO 流和资源做操作,必须逐一关闭IO 流和资源对象(从里层到外层),有异常也要做处理,直接在代码逻辑中关闭流资源存在很大的风险,一旦出现异常就会导致流资源没有正常关闭,导致占用的系统资源无法释放,累积之后会导致资源被占满,有的文件流操作未关闭会导致下次读写直接失败。

错误:

 FileInputStream in = null;
try {
     in = new FileInputStream(xxx);
     in.close();
} catch (xxxException e) {
     log.error(e);
} catch (IOException e) {
     log.error(e);
}

 

使用try-catch-finally,在finally中关闭流,注意流关闭的顺序,并且有异常时也要进行相应的处理。

正确:
finally{
    try {
        if(null != fileIn){
            fileIn.close();
        }
    } catch (Exception e) {
       log.error("流关闭异常" + e.getMessage());
    }
    try {
        if(null != out){
            out.close();
        }
    } catch (Exception e) {
        log.error("流关闭异常" + e.getMessage());
    }       
}

       推荐方式Java 7Try-With-Resource语句,在try-with-resource中声名一种资源,那么这个资源会在try中的代码执行完成或者出现异常之后自动关闭,不需要通过代码控制关闭,也不需要考虑关闭时会出现异常等等。

       注意该对象必须是实现了java.lang.AutoCloseable接口或者java.io.Closeable接口的对象。

try (FileInputStream inputStream = new FileInputStream(file)) {
    xxxxxx
} catch (FileNotFoundException e) {
    log.error(e);
} catch (IOException e) {
    log.error(e);
}

 

7.  方法抛出的异常,应该与本身的抽象层次相对

     抛出的异常越明确越好,减少和其他的耦合,其次异常明确之后,代码的可读性也更高。异常使用本身的抽象可以将方法名和异常信息匹配

错误

public void test() throws Exception { ... }

 

public void test() throws TestException { ... }

 

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。