异常(二):异常类

  1. 怎样理解 Throwable
    答:

    • Throwable 是所有异常类的父类
    • Throwable 类有两个主要参数:一个是 message,表示异常信息;另一个是 cause,表示触发该异常的其他异常
    • 异常可以形成一个异常链,上层的异常由底层的异常触发,cause 表示底层异常
    • Throwable 还有一个 public 方法用于设置 causeThrowable initCause(Throwable cause)Throwable 的某些子类没有带 cause 参数的构造方法,就可以通过这个方法来设置,这个方法最多只能被调用一次。
    • 在所有构造方法的内部,都有一句重要的方法调用:fillInStackTrace(),它会将异常栈信息保存下来,这是我们能看到异常栈的关键。
  2. Throwable 中常用的用于获取异常信息的方法有哪些?
    答:

    • void printStackTrace(),打印异常栈信息到标准错误输出流。
    • void printStackTrace(PrintStream s) / void printStackTrace(PrintWriter s),打印栈信息到指定的流。
    • String getMessage(),获取设置的异常 message
    • Throwable getCause(),获取异常的 cause
    • StackTraceElement[] getStackTrace(),获取异常栈每一层的信息,每个 StackTraceElement 包括文件名、类名、方法名、行号等信息。
  3. 异常类的体系是怎样的?
    答:

    • Throwable 是所有异常类的基类,它有两个子类:ErrorException
    • Error 表示系统错误或资源耗尽,即不可控的内部原因,由 Java 系统自己使用,应用程序不应抛出和处理。常见的子类有:VirtualMachineErrorOutOfMemoryErrorStackOverflowError
    • Exception 表示应用程序错误,即不可控的外部原因,它有很多子类,应用程序也可以通过继承 Exception 或其子类创建自定义异常。常见的子类有:IOExceptionRuntimeExceptionSQLException
  4. 怎么理解未受检异常和受检异常?
    答:

    • 未受检异常包括:RuntimeException 及其子类和Error 及其子类
    • 受检异常包括:Exception 及其除了 RuntimeException 之外的其他子类
    • RuntimeException 比较特殊,它的名字有点误导,因为其他异常也是运行时产生的,它表示的实际含义就是未受检异常。
    • 受检和未受检的区别在于 Java 如何处理这两种异常。对于受检异常,Java 会强制要求程序员进行处理,否则会有编译错误,而对于未受检异常则没有这个要求。有点类似于编译时和运行时的区别
  5. 为什么定义这么多不同的异常类?
    答:

    • 么多不同的异常类其实并没有比 Throwable 这个基类多多少属性和方法,大部分类在继承父类后只是定义了几个构造方法,这些构造方法也只是调用了父类的构造方法,并没有额外的操作。
    • 之所以定义这么多不同的异常类主要是为了名字不同异常类的名字本身就代表了异常的关键信息,无论是抛出异常还是捕获异常,使用合适的名字都有助于代码的可读性和可维护性。
  6. 怎样自定义异常?
    答:

    • 一般是继承 Exception 或者它的某个子类
    • 如果继承的父类是 RuntimeException 或它的某个子类,那么此时自定义异常也是未受检异常。
    • 如果继承的父类是 Exception 或它的除了 RuntimeException 之外的其他子类,那么此时自定义的异常是受检异常。