Java异常

Java异常分类结构:

  java.lang.Throwable  顶层父类

    |– Error错误:JVM内部的严重问题,如OOM,程序员无法在代码中处理(如StackOverflowError、OutOfMemoryError)。

    |–Exception异常:普通的问题。通过合理的处理,程序还可以回到正常执行流程。要求程序员要进行处理。

      |–RuntimeException:未检查异常(unchecked exception)。  

        这类异常是程序员的逻辑问题,由于程序员的疏忽导致的错误(如数组越界,空指针等)。Java编译器不进行强制要求处理。 也就是说,这类异常在程序中,可以进行处理,也可以不处理。 

      |–非RuntimeException:已检查异常(checked exception)、编译时异常。

        这类异常是由一些外部的偶然因素所引起的。Java编译器强制要求处理。也就是说,程序必须进行对这类异常进行处理,throw,throws或者try catch。

 

 

  稳定代码:无论如何都不会出错的代码

  非稳定代码:可能会出错的代码,需要进行异常捕获

 

  throw和throws的区别:

    throw是方法内部抛出异常类对象的关键字

    throws则用在方法signature上,表示方法调用者可通过此方法声明向上抛出异常对象

 

  异常的处理:

    如果异常在当前方法的处理能力范围之内且没有必要对外透出,那么就直接 捕获异常并做相应处理;否则向上抛出 , 由上层方法或者框架来处理。

    无论采用哪种方式处理异常 , 都严禁捕获异常后什么都不做或打印 行日 志了事。如果在方法内部处理异常 , 需要根据不同的业务场景进行定制处理 , 如重试、 回滚等操作。如果向上抛出异常,如上例 所示 , 需要在异常对象中添加上下文参数、 局部变量、运行环境等信息,这样有利于排查问题。

 

  处理异常的最佳实践:

    ①:当需要向上抛出异常的时候,需根据当前业务场景定义具有业务含义的异常,优先使用行业定义的异常或者团队内部定义好的。

      如在使用dubbo进行远程服务调用超时的时候会抛出DubboTimeoutException,而不是直接把RuntimeException抛出

    ②:请勿在finally代码块中使用return语句,避免返回值的判断变得复杂

    ③:捕获异常具体的子类,而不是Exception,更不是throwable。这样会捕获所有的错误,包括JVM抛出的无法处理的严重错误

    ④:切记更别忽视任何一个异常(catch住了不做任何处理),即使现在能确保不影响逻辑的正常运行,但是对于将来谁都无法保证代码会如何改动,别给子集挖坑

    ⑤:不要使用异常当做控制流程来使用,这是一个很奇葩也很影响性能的做法

    ⑥:清理资源,释放连接等操作一定要放在finally代码块中,防止内存泄露,如果finally块处理的逻辑比较多且模块化,我们可以封装成工具方法使用,代码会比较简洁

        

 

  try代码块:

    try-catch-finally 是处理异常的三部曲。当存在try时,可以只有catch代码块,也可以只有finally代码块,就是不能单独只有try代码块。

    注意:finally代码块是在return表达式后执行的,此时将要return的结果暂存起来,待finally代码块执行结束后再将之前暂存的结果返回。另外,避免在finally块中使用return操作,否则会导致返回值变得不可控。

 

 

END.

posted @ 2021-03-30 14:44  杨岂  阅读(42)  评论(0编辑  收藏  举报