Photo By Instagram sooyaaa
问题 12
你在开发中碰到过 ClassNotFoundException 和 NoClassDefFoundError 吗? 它们有什么区别?
我的答案
首先这俩个错误都代表着 JVM 无法找到相关的类而抛出的错误,但是它们发生的场景,以及类型却截然不同。
类型
从类型上来说 ClassNotFoundException 是 Exception 系的,而 NoClassDefFoundError 是 Error 系的,虽然他们都是 Throwable 的子孙,但是使用场景却截然不同。
Error 系的错误一旦抛出,则代表着这个错误是无法修复的,应用程序不应当去捕捉这个错误,因为这个类型的错误正常情况下永远也不会出现。
Exception 系的轻微一点,这种错误允许我们在应用程序中处理,是一种可以预知的错误。
发生场景
ClassNotFoundException 一般会在我们的应用程序去试图加载一个类的时候,发现当前类路径中无法找到该类的 class 文件而抛出的,例如如下几个方法:
Class 的 forName 方法
ClassLoader 的 findSystemClass 和 loadClass 方法
虽然 NoClassDefFoundError 也是在 JVM 试图加载一个类的时候发现类不存在然后抛出的错误,但是它是在我们使用 new 来实例化一个对象的时候抛出的。
如下我们做了一个小测试,定义了一个 Solution 类,然后在 Main 类中使用它,当 2 个类都编译完成以后,我们删除掉 Solution 类的 class 文件,然后运行 Main 类:
1 public class Main {
2
3 public static void main (String[] args) throws ClassNotFoundException {
4 try {
5 Solution solution = new Solution();
6 } catch (Throwable e) {
7 e.printStackTrace();
8 }
9
10 try {
11 Class.forName( "jvm.Solution" );
12 } catch (Exception e) {
13 e.printStackTrace();
14 }
15 System.out.println( "over" );
16 }
17 }
18
19 public class Solution {
20
}
此时我们会得到如下异常信息:
1java.lang.NoClassDefFoundError: jvm/Solution 2 at jvm.Main.main(Main.java:12) 3Caused by: java.lang.ClassNotFoundException: jvm.Solution 4 at java.net.URLClassLoader$1.run(URLClassLoader.java:372) 5 at java.net.URLClassLoader$1.run(URLClassLoader.java:361) 6 at java.security.AccessController.doPrivileged(Native Method) 7 at java.net.URLClassLoader.findClass(URLClassLoader.java:360) 8 at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 9 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308) 10 at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 11 ... 1 more 12java.lang.ClassNotFoundException: jvm.Solution 13 at java.net.URLClassLoader$1.run(URLClassLoader.java:372) 14 at java.net.URLClassLoader$1.run(URLClassLoader.java:361) 15 at java.security.AccessController.doPrivileged(Native Method) 16 at java.net.URLClassLoader.findClass(URLClassLoader.java:360) 17 at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 18 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
你会发现,使用 new 来初始化对象时候,抛出来的最外层是 NoClassDefFoundError 错误,然而它的底层还是因为 ClassNotFoundException 异常造成的。 而使用 Class.forName 去加载类呢,则会直接抛出 ClassNotFoundException 异常。
如上即为 ClassNotFoundException 和 NoClassDefFoundError 的区别,你 get 到了吗?
以上即为昨天的问题的答案,小伙伴们对这个答案是否满意呢?欢迎留言和我讨论。
又要到年末了,你是不是又悄咪咪的开始看机会啦。 为了广大小伙伴能充足电量,能顺利通过 BAT 的面试官无情三连炮,我特意推出大型刷题节目。 每天一道题目,第二天给答案,前一天给小伙伴们独立思考的机会。
点下“在看”,鼓励一下?