关于java NoClassDefFoundError

关于java  找不到类错误 的一些小实验

2011-5-7 7:33am    by 黄金龙

 

1

注意classpath 变量并没有设置 但是一样可以正常运行

在这个程序的基础之上 我们通过逐步更改来探究 package import  以及 classpath  的含义

1:在源程序 Hello.java 加入  package tools


 

2

 

3

编译通过了 但是在当前目录下是无法运行的。

这是因为package tools ;已经指定  hello class  是属于 tools 包的 你必须把编译后生成的  hello.class 文件放到 tools 的目录里边去。好我们来新建一个目录 tools ,并把生成的 hello.class 文件放进去。如图

 

4

现在我们来运行

J ava tools.Hello 或者  java tools/Hello 都将得到期望的结果。可以自己试一下。

运行命令cd ..

退到上层目录,试着调用hello. C lass 

 

5

注意classpath  并没有被设置 这个时候系统报错  NoClassDefFoundError

现在是classpath 发挥威力的地方了 。讲 tools  目录加入到 classpath 。在看看

 

6

G ood! 现在明白了吧! classpath  就是告诉系统到哪里去找我们的 class

现在你可以到任何目录下java tools .Hello  都将得到期望的结果 但是 java  后边必须接 Hello  的全名 即包括的他的包名(当然在一个 java 源文件中可以用 import  来引用包 这样在就不用写出全名了)。由于 class 所属的包是在源文件中写死的,我们不能单从 Hello.class 文件本名来查看它所属的

 

7

, 下面我们来看一种方法看看他到底是属于哪个包

看到了吧,你使用package  来编译一个 java 文件的时候 真正的类是  包名 . 类名,系统也是通过这个全名来找这个类的。还有你一定要把你编译的 java 文件放到 和你指定的  package

相应的目录结构中去,比如 若是 package  a.b.c; 则 这个文件必须放到   a/b/c/ (注意 windows 下的目录分隔符是 /  linux的是 / )看下图

 

当前目录已经被默认加入到class 的搜索中去了 不需要在 classpath 变量中显示指定。但是你若是要指定 classpath  就一定要把 .;  等加上。

 你若在使用的三方给的包(你自己写的也是一样)的时候千万不要改变它里边的目录结构,否则会出现出现 找不到 类的错误 ,而它“明明就那里”。你大概不希望用javap  来查看每一个 class  文件所属的包吧。

注:若用set  命令来是制定环境变量 只适用于当前的 cmd 窗口 要永久更改 环境变量就要在系统属性——高级——环境变量中更改。

总结

(1)  当你执行 java a.b.test  的时候 jvm 是通过 classpath 变量所指定的目录下寻找 a 目录,进入 a 目录,寻找 b 目录,进入 b 目录再寻找 test.class 文件 然后查看这个文件内的类是不是 a.b.test (通过 javap 来查看,前面有例子 ,图 7 ),如果是,则载入,不存在或不是则错误。另外可一通过代-verbose 参数来运行 java  可以看到整个的载入类的过程,例如:  java  -verbose a.test  他的输出很惊人(如果执行成功的话)脑袋都大了 ,但是不用担心,我们写的类基本上都是在最后载入的,因此只要看最后几行输出就好,(看下图,注意最后倒数 3 , 这是 java  verbose tools.Hello 的输出)

2

CLASSPATH的陷阱 

P.java文件存在一个非常有趣的陷阱。特别是对于早期的  Java  实现方案来说,类路径的正确设定通常都是很困难的一项工作。编写这本书的时候,我引入了 P.java 文件,它最初看起来似乎工作很正常。但在某些情 况下,却开始出现中断。在很长的时间里,我都确信这是  Java  或其他什么在实现时一个错误。但最后,我终于发现在一个地方引入了一个程序(即第  17 章要说明的 CodePackager.java ),它使用了一个不同的类 P 由于它作为一个工具使用,所以有时候会进入类路径里;另一些时候则不会这样。但只要它进入类路径,那么假若执行的程序需要寻找com.bruceeckel.tools 中的类, Java  首先发现的就是 CodePackager.java 中的  P 。此时,编译器会报告一个特定的方法没有找到。这当然是非常令人头疼的,因为我们在前面的类 里明明看到了这个方法,而且根本没有更多的诊断报告可为我们提供一条线索,让我们知道找到的是一个完全不同的类(那甚至不是 public  的)。乍一看来,这似乎是编译器的一个错误,但假若考察 import 语句,就会发现它只是说: 在这里可能发现了 P” 。然而,我们假定的是编译器搜索自己类路径的任何地方,所以一旦它发现一个 P ,就会使用它;若在搜索过程中发现了 错误的 一个,它就会停止搜索。这与我们在前面表述的稍微有些区别,因为存在一些讨厌的类,它们都位于包内。而这里有一个不在包内的 P ,但仍可在常规的类路径搜索过程中找到。如果您遇到象这样的情况,请务必保证对于类路径的每个地方,每个名字都仅存在一个类。 (摘自 <thinking in java>第四版  5.1 

相信都看的明白可以自己写点程序验证一下

E dited  by  黄金龙

嘿嘿!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值