Throwable 类是 Java 语言中所有错误或异常的超类。只有当对象是此类(或其子类之一)的实例时,才能通过 Java 虚拟机或者 Java 的 throw 语句抛出。类似地,只有此类或其子类之一才可以是 catch 子句中的参数类型。
Error 是 Throwable 的子类,用于指示应用程序不应该试图捕获的严重问题。Error 也叫系统级异常,它是为无法预计的,程序无法处理的异常错误,表示运行应用程序过程中出现了较严重问题。一般情况都是在JVM上出现了问题。
在执行该方法期间,无需在其 throws 子句中声明可能抛出但是未能捕获的 Error 的任何子类,因为这些错误是不确定的不会重复出现的。
AnnotationFormatError
当注释解析器试图从类文件读取注释并确定注释出现异常时,抛出该错误。
IOError
当发生严重的 I/O 错误时,抛出此错误。
ThreadDeath
调用 Thread 类中带有零参数的 stop 方法时,受害线程将抛出一个 ThreadDeath 实例。
仅当应用程序在被异步终止后必须清除时才应该捕获这个类的实例。如果 ThreadDeath 被一个方法捕获,那么将它重新抛出非常重要,因为这样才能让该线程真正终止。
如果没有捕获 ThreadDeath,则顶级错误处理程序不会输出消息。 虽然 ThreadDeath 类是“正常出现”的,但它只能是 Error 的子类而不是 Exception 的子类,因为许多应用程序捕获所有出现的 Exception,然后又将其放弃。
LinkageError
LinkageError 的子类指示一个类在一定程度上依赖于另一个类;但是,在编译前一个类之后,后一个类发生了不相容的改变。它一共有7个直接子类。
VirtualMachineError
当 Java 虚拟机崩溃或用尽了它继续操作所需的资源时,抛出该错误。子类有: InternalError
(该异常指示 Java 虚拟机中出现一些意外的内部错误), OutOfMemoryError
(因为内存溢出或没有可用的内存提供给垃圾回收器时,Java 虚拟机无法分配一个对象,这时抛出该异常), StackOverflowError
(当应用程序递归太深而发生堆栈溢出时,抛出该错误), UnknownError
(当 Java 虚拟机中出现一个未知但严重的异常时,抛出该错误)。
同样作为Throwable的子类,既然Error是系统级异常,与之对应的Exception就是应用级异常。这种异常通常都是可能预料到的,由应用抛出该类异常,执行方法时再捕获该类异常。
Exception的直接子类有很多,大概有数十个,我们将它的所有子类分为两类:
运行时异常1,运行时异常(RuntimeException)是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。程序编译时是不知道到底会不会触发该异常的,只有程序运行起来才知道。它的子类也有很多,例如有空指针异常(NullPointerException), 对象强制转换异常(ClassCastException)等等。 2,因为运行时异常的不确定性,所以对于程序中抛出的RuntimeException及其子类在程序执行方法期间是不需要我们强制捕获处理它的。 3,RuntimeException跟Error性质上差不多,都是在程序运行期间可能会产生的异常。但是Error是系统级的异常大都是JVM相关的异常,而RuntimeException则是应用程序级别的异常。
其他应用异常1,其他应用异常就是Exception的所有子类里除了RuntimeException外的异常,这些异常都是在执行之前可预见的异常。例如IOException、SQLException等以及用户自定义的Exception异常。 2,这些异常与RuntimeException不同的是编译器强制要求必须捕获处理他们,即如果程序某处抛出了异常,那么在执行方法前一定要先捕获异常。
try{ // 可能会抛出异常的代码 }catch(Exception e){ // 捕获异常的位置 }finally{ // 无论有没有抛出异常都会执行的代码 } 复制代码
在 try
代码块中的语句一旦抛出异常后面未执行的代码将不会在执行,直接跳转到 catch
中。
捕获对应异常 catch
可以有很多个,JVM会从第一个找起。尽量把子异常放在前面,如果你抛出的异常在它的父类后面就直接进到父类异常里了。
代码块 finally
也会有不执行的时候,如JVM 过早终止(调用 System.exit(int));在 finally 块中抛出一个未处理的异常;计算机断电、失火、或遭遇病毒攻击。