我们在平时写代码都能接触到Exception和Error,今天来说说它们之间的区别。
Exception和Error类都是继承Throwable类

Throwable

Throwable类是Java语言中所有错误errors和异常exceptions的父类。只有继承于Throwable的类或者其子类才能被抛出,还有带有Java中的@throw注解的也可抛出。·
Java规范中,对非受查异常和受查异常的定义:

“The unchecked exception classes are the run-time exception classes and the error classes. “The checked exception classes are all exception classes other than the unchecked exception classes. That is, the checked exception classes are Throwable and all its subclasses other than RuntimeException and its subclasses and Error and its subclasses.

除了RuntimeException和其子类,以及error和其子类,其他所有异常都是checkeException。
Throwable的属性和方法:

  1. // 返回抛出异常的详细信息
  2. public string getMessage();
  3. public string getLocalizedMessage();
  4. //返回异常发生时的简要描述
  5. public public String toString();
  6. // 打印异常信息到标准输出流上
  7. public void printStackTrace();
  8. public void printStackTrace(PrintStream s);
  9. public void printStackTrace(PrintWriter s)
  10. // 记录栈帧的的当前状态
  11. public synchronized Throwable fillInStackTrace();

此外,Throwable的父类是Object类,常用方法还有继承父类的getClass()和getName()方法。

Exception

Exception有两种异常,一种是RuntimeException,一种是CheckedException,两种异常都应该去捕获。检查型异常必须在源码中进行捕获处理,这是编译检查的一部分。除了RuntimeException及其子类之外的异常都是检查型异常。非检查型异常就是所谓的RuntimeException,类似NullPointerException,ArrayIndexOfBoundException就是非检查型异常,通常是可以通过编码避免的逻辑错误,具体根据需要判断是否需要捕获,编译期不检查,如果抛出了非检查型异常,那就是编码逻辑有问题,要解决。

RuntimeException

序号 异常名称 异常描述
1 ArrayIndexOutOfBoundsException 数组越界异常
2 NullPointerException 空指针异常
3 IllegalArgumentException 非法参数异常
4 NegativeArraySizeException 数组长度为负异常
5 IllegalStateException 非法状态异常
6 ClassCastException 类型转换异常

CheckedException

序号 异常名称 异常描述
1 NoSuchFieldException 表示该类没有指定名称抛出来的异常
2 NoSuchMethodException 表示该类没有指定方法抛出来的异常
3 IllEgalAccessException 不允许访问某个类的异常
4 ClassNotFoundException 类没有找到抛出异常

与Exception有关关键字
throws,throw,try,catch,finally

  • throw语句用在方法体内,表示抛出异常,有方法体内的语句处理;throws语句用在方法声明后面,表示再抛出异常,由该方法的调用者处理。
  • throw是具体向外抛异常的动作,抛出一个异常实例;throws主要是声明这个方法会抛出这种类型的异常,使调用者知道要捕获这个异常。
  • throw后只能跟一个异常对象,throws后面可以一次声明多种异常类型。

Error

Error是程序无法处理的错误,表示运行应用程序中较严重问题。大多数错误与代码编写者执行操作无关,而表示代码运行时JVM出现的问题。这些错误是不可检查的,因为他们在应用程序的控制和处理能力之外,而且绝大多数都是程序运行时不允许出现的状况,比如OutOfMemoryError和StackOverflowError。

一道经典的面试题
NoClassDefFoundError 和 ClassNotFoundException 有什么区别
在类的加载过程中, JVM 或者 ClassLoader 无法找到对应的类时,都可能会引起这两种异常/错误,由于不同的 ClassLoader 会从不同的地方加载类,有时是错误的 CLASSPATH 类路径导致的这类错误,有时是某个库的 jar 包缺失引发这类错误。NoClassDefFoundError 表示这个类在编译时期存在,但是在运行时却找不到此类,有时静态初始化块也会导致 NoClassDefFoundError 错误。

“ClassLoader 是类路径装载器,在Java 中,类路径装载器一共有三种两类 一种是虚拟机自带的 ClassLoader,分为三种

  • 启动类加载器(Bootstrap) ,负责加载 $JAVAHOME/jre/lib/rt.jar
  • 扩展类加载器(Extension),负责加载 $JAVAHOME/jre/lib/ext/*.jar
  • 应用程序类加载器(AppClassLoader),加载当前应用的 classpath 的所有类

另一方面,ClassNotFoundException 与编译时期无关,当你尝试在运行时使用反射加载类时,ClassNotFoundException 就会出现。
简而言之,ClassNotFoundException 和 NoClassDefFoundError 都是由 CLASSPATH 中缺少类引起的,通常是由于缺少 JAR 文件而引起的,但是如果 JVM 认为应用运行时找不到相应的引用,就会抛出 NoClassDefFoundError 错误;当你在代码中显示的加载类比如 Class.forName() 调用时却没有找到相应的类,就会抛出 java.lang.ClassNotFoundException。

  • NoClassDefFoundError 是 JVM 引起的错误,是 unchecked,未经检查的。因此不会使用 try-catch 或者 finally 语句块;另外,ClassNotFoundException 是受检异常,因此需要 try-catch 语句块或者 try-finally 语句块包围,否则会导致编译错误。
  • 调用 Class.forName()、ClassLoader.findClass() 和 ClassLoader.loadClass() 等方法时可能会引起 java.lang.ClassNotFoundException。
  • NoClassDefFoundError 是链接错误,发生在链接阶段,当解析引用找不到对应的类,就会触发;而 ClassNotFoundException 是发生在运行时的异常。