原创

Java的异常Exception,springboot配置全局异常

什么是异常?

程序开发和运行过程中会出现编译错误和运行错误。编译错误容易被发现并排除,而运行错误(逻辑错误和异常)很难预料。因此为了程序的稳定性和可靠性,就需要对程序异常处理和保护。
异常( Exception ):正常程序流程所不能处理或者没有处理的异常情况或异常事件。
异常机制,是指程序不正常时的处理方式。具体来说,异常机制提供了程序退出的安全通道。当出现错误后,程序执行的流程发生改变,程序的控制权转移到异常处理器。

为什么要使用异常?

传统的程序设计中会像下面的伪代码形式来处理错误:

 执行一个任务
          if   前一个任务未能正确执行

               执行错误处理

              执行下一个任务

         if   前一个任务未能正确执行

             执行错误处理

而这样只会让程序更加复杂!

异常的一般性语法为:

    try {
        // 有可能抛出异常的代码
    } catch (Exception e) {
        // 异常处理
    } finally {
        // 无论是否捕获到异常都会执行的程序
    }

Java异常体系

  • Throwable 类是整个Java异常体系的超类,都有的异常类都是派生自这个类。包含Error和Exception两个直接子类。
  • Error 表示程序在运行期间出现了十分严重、不可恢复的错误,在这种情况下应用程序只能中止运行,例如JAVA虚拟机出现错误。在程序中不用捕获Error类型的异常。一般情况下,在程序中也不应该抛出Error类型的异常。
  • Exception 是应用层面上最顶层的异常类,包含RuntimeException(运行时异常)和 Checked Exception(受检异常)。
    ------RuntimeException是一种Unchecked Exception,即表示编译器不会检查程序是否对RuntimeException作了处理,在程序中不必捕获RuntimException类型的异常,也不必在方法体声明抛出RuntimeException类。一般来说,RuntimeException发生的时候,表示程序中出现了编程错误,所以应该找出错误修改程序,而不是去捕获RuntimeException。常见的RuntimeException有NullPointException、ClassCastException、IllegalArgumentException、IndexOutOfBoundException等。
    ------Checked Exception是相对于Unchecked Exception而言的,Java中并没有一个名为Checked Exception的类。它是在编程中使用最多的Exception,所有继承自Exception并且不是RuntimeException的异常都是Checked Exception。JAVA 语言规定必须对checked Exception作处理,编译器会对此作检查,要么在方法体中声明抛出checked Exception,要么使用catch语句捕获checked Exception进行处理,不然不能通过编译。常用的Checked Exception有IOException、ClassNotFoundException等。

受检异常(checked exception)

必须处理或者向上抛出
我们必须要对底层抛出来的受检异常进行处理,处理方式有try...catch...或者向上抛出(throws),否则程序无法通过编译。

package demo.blog.java.exception;

/**
 * 必须对底层抛出的异常进行处理
 * @author xialei
 * @version 1.0 2016年5月18日下午10:42:53
 */
public class CheckedException {

    public static void main(String[] args) {
        throwException(); // 编译不通过,必须对底层抛出的异常进行处理
    }

    public static void throwException() throws Exception {
        throw new Exception();
    }
}

思考:

  1. 问题:我可以只throw new Exception(); 而不在方法名那里throws Exception吗?如:

     public static void throwException(){
         throw new Exception();
     }
    

    答案:不可以,必须 try catch 处理掉或者throws给上层处理。

  2. 问题:我可以只在方法名那里throws Exception,而不在方法里面 throw new Exception();吗?

     public static void throwException() throws Exception {
         System.out.println("hello world");
     }
    

    答案:可以,不会报错,但是没有明确的throw的话就不知道是哪个地方抛出来的异常,有些异常就是不知道是运行到哪一步会抛出来或者无需关心哪一步会抛出来的话,那就只throws不用throw,如果是要明确是运行到哪个地方抛出来的话则用throw。

  3. 问题:我调用一个方法但是里面没有抛出过XxException()这个异常是继承Exception类的。我可以在外面即调用的地方进行try catch对这个没有抛出过的异常自己想处理就处理吗?
    答案:不可以。

运行时异常(runtime exception)

运行时异常(runtime exception)与受检异常(checked exception)的最大区别是不强制对抛出的异常进行处理。所有的运行时异常都继承自RuntimeException这个类,别问为什么,Java是这么规定的。与受检异常类似的例子,如果抛出的是运行时异常,就算不捕获这个异常,程序也可以编译通过。

/*
 * 个人主页:http://hinylover.space
 *
 * Creation Date: 2016年5月18日 下午11:02:57
 */
package demo.blog.java.exception;


/**
 * 编译通过
 * @author xialei
 * @version 1.0 2016年5月18日下午11:02:57
 */
public class MyRuntimeException {

    public static void main(String[] args) {
        myRuntimeException(); // 可以正常编译
    }

    public void myRuntimeException() {
        throw new RuntimeException(); 
    }

}

思考:

  1. 问题:我可以只throw new RuntimeException()或自定义的RuntimeException继承类; 而不在方法名那里throws RuntimeException()吗?
    答案:可以,编译可以通过,不会报错。非检查异常无须进行try catch处理或者throws给上层处理都不会报错。
  2. 问题:我在方法名那里throws RuntimeException()或自定义的RuntimeException继承类 外面就能 try catch 进行处理吗?
    答案:外面可以try catch进行处理,但是不会提示,即处不处理都没有关系,处理的话要自己知道里面抛出的是什么。而且就算是里面没有抛出的RuntimeException或自定义的继承它的异常,都可以在外面自己try catch处理。
  3. 问题:我调用一个方法但是里面没有抛出过XxException()这个异常是继承RuntimeException类的。我可以在外面即调用的地方进行try catch对这个没有抛出过的异常自己想处理就处理吗?
    答案:可以,同问题2.

异常的使用

自我总结:
像在封装插件的时候,如果我的异常是强制(强制一般是可能经过处理后还要返回给用户看到的)要给使用插件的程序决定对这个异常进行怎么样处理的话,则使用受检查的异常(即继承Exception)抛出给外层进行处理。这种情况下一般是自定义异常,每个异常都自定义一个,因为外层根据不同的异常可以做不同的处理,定义不同的错误码和错误信息等。
像在封装插件的时候,如果我这个异常是非强制(不需要用户知道,开发人员知道,且出现这种错误一般是需要开发人员进行修正代码或者配置)的情况下,则使用运行时异常,可以直接在插件里面抛出然后由封装的全局异常捕获进行异常处理即可。当然也可以封装一个插件的统一异常(此时就不用继承RuntimeException了而是继承Exception了),然后抛给使用插件的程序进行处理和记录日志等。

运行时异常正常来说一般都是逻辑错误或者代码错误导致,正确的处理方式应该是打印或者记录日志,然后找到这个异常,对异常进行处理,通常来说这种异常也是开发人员进行处理,不需要被用户感知的。

参考资料

【系列】重新认识Java语言——异常(Exception)
https://blog.csdn.net/xialei199023/article/details/63251277 这篇的参考还是比较好的
Java的异常Exception
https://blog.csdn.net/jin970505/article/details/78418677

为了“偷懒”,无论什么情况都使用运行时异常,这样就可以不用费劲处理异常了,轻轻松松。但是,现在没事不代表以后不出事,这无疑为代码埋下了隐患。如果在调用一个方法时,该方法并没有显式地抛出异常,也没有在javadoc中强调,我们就不会知道调用这段代码可能发生的异常情况,那些可能出现的异常情况对我们来说是透明的。
https://blog.csdn.net/xialei199023/article/details/63251277

SpringBoot配置全局异常捕获 https://blog.csdn.net/hz_940611/article/details/80737326
SpringBoot配置全局异常 https://www.cnblogs.com/platycoden/p/9799900.html

正文到此结束
本文目录