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

简介:

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

  ClassNotFoundException

  ClassNotFoundException这个错误,比较常见也好理解。

  原因:就是找不到指定的class。

  常见的场景就是:

  1 调用class的forName方法时,找不到指定的类

  2 ClassLoader 中的 findSystemClass() 方法时,找不到指定的类

  3 ClassLoader 中的 loadClass() 方法时,找不到指定的类

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

复制代码
 1 package test321;
 2 
 3 public class test {
 4  public static void main(String[] args) {
 5   try {
 6    Class.forName("test321.hello");
 7   } catch (ClassNotFoundException e) {
 8    e.printStackTrace();
 9   }
10  }
11 }
复制代码

  此时,程序会到当前的目录中寻找指定位置test321.hello这个class。

  并且这个类也是可以正常执行的。

  但是,我们修改一下加载的类名,这样显然是找不到指定的类的。

复制代码
 1 package test321;
 2 
 3 public class test {
 4  public static void main(String[] args) {
 5   try {
 6    Class.forName("test321.hello1");
 7   } catch (ClassNotFoundException e) {
 8    e.printStackTrace();
 9   }
10  }
11 }
复制代码

  此时就会报错!

复制代码
报错!
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,在使用的时候需要加上包名才可以

  下面做了一个小例子!

  在没有包名的情况下,我们看一下正常情况是什么样子的。

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

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

复制代码
1 package ccc;
2 
3 public class test {
4  public static void main(String[] args) {
5   System.out.println("test");
6  }
7 }
复制代码

  很明显,报错信息中指出了包的信息!那么怎么办呢?

  在编译时,加上【   -d .   】这样可以把当前的目录加入到classpath中。

  在使用时,加上包名就可以了!

  也就是说,这个含有包名的类,编译时,需要指定classpath的路径,并且使用的时候指定包名全路径,才可以。

 

  参考资料

  1 http://blog.csdn.net/magister_feng/article/details/7459151

  2 http://www.blogjava.net/leekiang/archive/2007/04/26/113810.html

  3 http://blog.sina.com.cn/s/blog_65c507190100hzs0.html

本文转自博客园xingoo的博客,原文链接:java.lang.ClassNotFoundException与java.lang.NoClassDefFoundError的区别,如需转载请自行联系原博主。
相关文章
|
1天前
|
安全 Java 索引
带你快速掌握Java中的String类和StringBuffer类(详解常用方法 | 区别 )
带你快速掌握Java中的String类和StringBuffer类(详解常用方法 | 区别 )
|
3天前
|
缓存 Java 数据库连接
java面试题目 强引用、软引用、弱引用、幻象引用有什么区别?具体使用场景是什么?
【6月更文挑战第28天】在 Java 中,理解和正确使用各种引用类型(强引用、软引用、弱引用、幻象引用)对有效的内存管理和垃圾回收至关重要。下面我们详细解读这些引用类型的区别及其具体使用场景。
12 3
|
5天前
|
Java
Java中代码块区别及代码示例
Java中代码块区别及代码示例
|
6天前
|
自然语言处理 Java 数据处理
Java IO流全解析:字节流和字符流的区别与联系!
【6月更文挑战第26天】Java IO流涵盖字节流与字符流。字节流(InputStream/OutputStream)处理数据单位为字节,适用于二进制和文本,而字符流(Reader/Writer)专注于文本,处理单位为字符,处理编码转换。字符流在字节流基础上添加编码处理,以装饰器模式实现。文件复制示例展示了两者区别:字节流直接复制所有数据,字符流处理字符编码。理解并选择适当流类型对优化程序至关重要。
|
7天前
|
算法 Java 机器人
Java中的异常处理:Checked与Unchecked的区别
Java中的异常处理:Checked与Unchecked的区别
|
7天前
|
Java
【逻辑运算符】在Java中 &&和&的区别 ||和|的区别
【逻辑运算符】在Java中 &&和&的区别 ||和|的区别
9 0
|
11天前
|
Java
Java中Comparable接口和Comparator接口的区别(如果想知道Java中Comparable接口和Comparator接口的区别,那么只看这一篇就足够了!)
Java中Comparable接口和Comparator接口的区别(如果想知道Java中Comparable接口和Comparator接口的区别,那么只看这一篇就足够了!)
|
15天前
|
Java
Java编程不再难:一文看懂抽象类与接口的区别和联系!
【6月更文挑战第17天】在Java OOP中,抽象类与接口助你构建复杂应用。以图书管理系统为例,抽象类`Book`作为基类提供共享属性和方法,不直接实例化。接口如`HasChapters`和`HasIssues`定义特殊行为。抽象类支持部分实现,单继承,适合共享行为;接口仅含常量和抽象方法,多实现,强调行为规范。通过继承和实现,实现代码复用和系统扩展性。理解两者异同,是提升Java编程能力的关键。
|
19天前
|
Java C++
Java和C++的一些区别
Java和C++的一些区别
|
20天前
|
Java
Java基础7-一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别(二)
Java基础7-一文搞懂抽象类和接口,从基础到面试题,揭秘其本质区别(二)
18 0