相信java的開發(fā)者經(jīng)常會遇到這兩個異常,乍一看兩個就長得很像,有時候真的是老虎,老鼠傻傻讓人分不清楚。
1. 兩者對比
| 類別 | ClassNotFoundException | NoClassDefFoundError |
|---|---|---|
| 含義 | 找不到類定義 | 找不到類定義 |
| 繼承 | extends ReflectiveOperationException | extends LinkageError |
| 類型 | 反射操作引起的一種異常 | 一種鏈接錯誤 |
| 捕獲 | catch Exception/Throwable | catch Error/Throwable |
| 原因 | 通過反射根據(jù)指定類名無法找到類時,會引起該異常 | 編譯時有類定義,運行時丟失類定義會引起該異常。運行時類定義丟失往往有兩種情況:1)類不在ClassPath內(nèi),導(dǎo)致無法加載類定義,即由ClassNotFoundException引起。2)類初始化失敗,導(dǎo)致加載不到類定義,此時會伴隨著一個初始化異常(ExceptionInInitializerError)。 |
2. 兩者關(guān)系
NoClassDefFoundError可由ClassNotFoundException引起。
3. 兩者定義

NoClassDefFoundError doc
當(dāng)JVM或類加載器去加載一個類定義(無論是通過普通的方法調(diào)用,還是用new語句去創(chuàng)建該類的實例所觸發(fā)的類加載),如果該類的定義丟失,那么就會拋出NoClassDefFoundError.
被加載的類定義在當(dāng)前執(zhí)行類編譯時是存在的,但是再也找不到了。

ClassNotFound doc
當(dāng)應(yīng)用使用類的字符串名,通過以下方式嘗試去加載類,但是根據(jù)指定的名稱無法找到類定義時會拋出ClassNotFoundException:
1)Class.forName()
2)ClassLoader.findSystemClass()
3)ClassLoader.loadClass()
4. 實例
4.1 ClassNotFoundExcption
package qiweiTest;
public class ClassNotFoundExcptionTest {
public static void main(String[] args) {
Class.forName("anyNoexistClassName"); // 任何一個不存在的className
}
}
4.2 NoClassDefError
4.2.1 類不在ClassPath引發(fā)的異常
package qiweiTest;
public class NoClassDefErrorTest {
// 運行時,刪除ClassPath中的ClassNotFoundExceptionTest.class
public static void main(String[] args) {
ClassNotFoundExceptionTest.class.getClass();
}
}
輸出:
Exception in thread "main" java.lang.NoClassDefFoundError: qiweiTest/ClassNotFoundExceptionTest
at qiweiTest.NoClassDefErrorTest.main(NoClassDefErrorTest.java:9)
Caused by: java.lang.ClassNotFoundException: qiweiTest.ClassNotFoundExceptionTest
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
... 1 more
4.2.2 類初始化失敗引發(fā)的異常
package qiweiTest;
public class NoClassDefErrorTest2 {
public static void main(String[] args) {
int tmp;
try {
tmp = InterClass.a;
} catch (Throwable e) {
// 異常類型:ExceptionInInitializerError
e.printStackTrace();
}
try {
tmp = InterClass.a;
} catch (Throwable e) {
// 異常類型:NoClassDefFoundError
e.printStackTrace();
}
}
static class InterClass {
static int a;
static {
a = 1 / 0;
}
}
輸出:
java.lang.ExceptionInInitializerError
at qiweiTest.NoClassDefErrorTest2.main(NoClassDefErrorTest2.java:8)
Caused by: java.lang.ArithmeticException: / by zero
at qiweiTest.NoClassDefErrorTest2$InterClass.<clinit>(NoClassDefErrorTest2.java:22)
... 1 more
java.lang.NoClassDefFoundError: Could not initialize class qiweiTest.NoClassDefErrorTest2$InterClass
at qiweiTest.NoClassDefErrorTest2.main(NoClassDefErrorTest2.java:13)