首先从语法上来说,ClassNotFoundException是一个Exception,也就是个异常,而且是一个非运行时异常,需要显示处理异常,NoClassDefFoundError是一个Error,也就是个错误。Error不用显示处理,一般发生Error错误会导致整个线程终止运行。
接下来我们先做个实验,看一下结果,然后再来总结。
实验1:Class.forName加载类
测试代码如下
public class Demo1 {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> demo2 = Class.forName("Demo2");
System.out.println(demo2);
}
}
public class Demo2 {
public void test1() {
System.out.println("demo2 test1");
}
}
然后我们编译Demo1,编译结果如下:可以看到,Demo2.java并没有被编译为对应的class文件,因为我们在程序中并没有显式地使用到Demo2这个类。
此时我们运行Demo1可以看到报错ClassNotFoundException。
实验2:new一个对象然后删除class文件
测试代码如下:
public class Demo1 {
public static void main(String[] args) {
Demo2 demo2 = new Demo2();
System.out.println(demo2);
}
}
public class Demo2 {
public void test1() {
System.out.println("demo2 test1");
}
}
由于我们在程序中显式地用到了Demo2这个类,所以Demo2也同时被编译了出来,这时我们运行Demo1肯定是没问题的,但是我们把Demo2.class删除之后再运行。
运行结果如下:可以看到报错NoClassDefFoundError,但是我们查看Caused by可以发现,导致NoClassDefFoundError的原因其实还是ClassNotFoundException。
从上面可以看出来,当我们通过字符串形式加载一个类时,可能会报ClassNotFoundException异常,当我们通过new一个对象的方式时,成功编译后,再把对应的class文件删除时,就会报NoClassDefFoundError错误。
其实,在jdk文档中已经说得很明确了。从文档说明中可以看出,当我们通过字符串形式来加载一个类时,有可能会报ClassNotFoundException异常。当通过new关键字使用某个类但是找不到这个类时,会报NoClassDefFoundError错误。