但行好事  莫问前程

java.lang.ClassNotFoundException与java.lang.NoClassDefFoundError的区别

以前一直没有注意过这个问题,前两天机缘巧合上网查了一下,然后自己测试验证了一下。虽然网上说法很多,但是关于NoClassDefFoundError并没有给出一个样例,所以一直无法理解,索性自己验证了一下,收获还不少。

ClassNotFoundException

ClassNotFoundException这个错误,比较常见也好理解。
原因:就是找不到指定的class。
常见的场景就是
1. 调用class的forName方法时,找不到指定的类
2. ClassLoader 中的 findSystemClass() 方法时,找不到指定的类
3. ClassLoader 中的 loadClass() 方法时,找不到指定的类

开发者平时会有这样一种使用方法,类似JDBC加载驱动!

package test321;

public class test {
 public static void main(String[] args) {
  try {
   Class.forName("test321.hello");
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
 }
}

此时,程序会到当前的目录中寻找指定位置test321.hello这个class。并且这个类也是可以正常执行的。
但是,我们修改一下加载的类名,这样显然是找不到指定的类的。

package test321;

public class test {
 public static void main(String[] args) {
  try {
   Class.forName("test321.hello1");
  } catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
 }
}

此时就会报错!

java.lang.ClassNotFoundException: test321.hello1
 at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
 at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
 at java.security.AccessController.doPrivileged(Native Method)
 at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
 at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
 at java.lang.Class.forName0(Native Method)
 at java.lang.Class.forName(Class.java:190)
 at test321.test.main(test.java:6)

原因就是找不到指定的string对应的class文件。

NoClassDefFoundError

这个就比较奇葩了,查找其他的资料是说,通过了编译,但是使用的时候,比如new的时候会出错。
通过查找资料,搜集到如下的场景:

  1. 类依赖的class或者jar不存在
  2. 类文件存在,但是存在不同的域中
  3. 大小写问题,javac编译的时候是无视大小的,很有可能你编译出来的class文件就与想要的不一样!这个没有做验证。

针对上面的第二点,做了个关于包名的验证:
另一种情况就是由于你通过了编译,但是这个类是有包名的,因此在编译时需要指定classpath,在使用的时候需要加上包名才可以。
下面做了一个小例子!
在没有包名的情况下,我们看一下正常情况是什么样子的。

public class test {
  public static void main(String[] args) {
   System.out.println("test");
  }
}

·
而如果这个类中包含包名,那么按照上面的方法编译,使用时就会报错!

package ccc;

public class test {
 public static void main(String[] args) {
  System.out.println("test");
 }
}

1
很明显,报错信息中指出了包的信息!那么怎么办呢?在编译时,加上【 -d . 】这样可以把当前的目录加入到classpath中。
1
在使用时,加上包名就可以了!也就是说,这个含有包名的类,编译时,需要指定classpath的路径,并且使用的时候指定包名全路径,才可以。

打赏
欢迎关注人生设计师的微信公众账号
公众号ID:longjiazuoA

未经允许不得转载:人生设计师 » java.lang.ClassNotFoundException与java.lang.NoClassDefFoundError的区别

分享到:更多 ()

人生设计师-接受不同的声音

联系我关于我