Java 面试题:NoClassDefFoundError 和 ClassNotFoundException 有什么区别?
先看看 Error 和 Exception 有什么区别?
关于 Error 和 Exception 的区别 网上的答案都很多了,这里简单叙述:
- Java 的异常处理机制的基本组成类型:
Error 类 和 Exception 类 ,它们都是继承了 Throwable 类,在 java 中 Throwable 类型的实例才可以被抛出或捕获。
-
Error(错误) 表示主要是由于系统资源不足而出现的问题,我们的应用程序在正常情况下不会捕捉到这类问题。比如 OutOfMemoryError 之类。此时程序是处于非正常,不可逆的状态;Error 主要发生在运行时,属于 unchecked 类型。
-
Exception(异常)是指在运行时和编译时可能出现的问题。它主要发生在开发人员编写的代码中。 异常分为检查型异常(checked)和未检查型异常(unchecked)两类,可检查异常在源代码必须清楚地进行捕获处理。
-
Throwable 类是 Java 语言中所有 Error 错误和 Exception 异常的超类。 只有作为此类(或其子类之一)的实例对象才会被 JVM 或者 throw 语句抛出。 同样,只有这个类或其任一子类可以作为 catch 子句中的参数类型。 为了检查编译时的异常, Throwable 和任何 Throwable 的子类 (除了 RuntimeException 或 Error 的子类)都被视为已检查异常。
@adrian-jser : 假如你开车上山,车坏了,你拿出工具箱修一修,修好继续上路(Exception 被捕获,从异常中恢复,继续程序的运行),车坏了,你不知道怎么修,打电话告诉修车行,告诉你是什么问题,要车行过来修。(在当前的逻辑背景下,你不知道是怎么样的处理逻辑,把异常抛出去到更高的业务层来处理)。你打电话的时候,要尽量具体,不能只说我车动不了了。那修车行很难定位你的问题。(要补货特定的异常,不能捕获类似 Exception 的通用异常)。还有一种情况是,你开车上山,山塌了,这你还能修吗?(Error:导致你的运行环境进入不正常的状态,很难恢复)
简介
当 JVM 在 classpath 上找不到请求的类时,ClassNotFoundException 和 NoClassDefFoundError 都会发生。虽然它们看起来意思很像,这两者之间还是有一些代码差异。
ClassNotFoundException
ClassNotFoundException 是一个检查型异常,当程序试图通过其完全限定的名称加载一个类,但在 classpath 上找不到它的定义时,就会发生异常。
这种情况主要发生在使用Class.forName()、ClassLoader.loadClass() 或 ClassLoader.findSystemClass()
来加载类的时候。因此,我们在使用反射时需要更加注意防范java.lang.ClassNotFoundException
。
例如,我们尝试启动一个 jdbc driver,但我们不给出它的依赖。
@Test(expected = ClassNotFoundException.class)
public void givenNoDrivers_whenLoadDriverClass_thenClassNotFoundException()
throws ClassNotFoundException {
//将会抛出 ClassNotFoundException
Class.forName("oracle.jdbc.driver.OracleDriver");
}
NoClassDefFoundError
NoClassDefFoundError 是一个致命的错误,当 JVM 不能在 通过使用新的关键字来实例化一个类 或 用方法调用加载一个类 的情况下找到类的定义,就会发生 NoClassDefFoundError。
当编译器可以成功编译类,但 Java 运行时无法定位类文件时,就会发生该错误。通常发生在执行静态语句块或初始化类的静态成员变量时出现异常,所以类初始化失败。
开篇解答
-
NoClassDefFoundError 是在编译时依赖的类在运行时找不到了,一般是缺少依赖的 jar 包导致的。编译好的 class 文件中已经引用了这个类,JVM 无法继续往下运行,所以这是一个 Error(unchecked)
-
ClassNotFoundException 是在 classpath 下找不到这个类,编译时不依赖,运行时尝试去加载,找不到的话程序可以进行处理,是一个 checked Exception。