首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

javac和java的路径有关问题

2013-11-09 
javac和java的路径问题javac和java的路径问题?设定项目目录为packageTest,举三个例子来讨论javac和java两

javac和java的路径问题

javac和java的路径问题

?

设定项目目录为packageTest,举三个例子来讨论javac和java两个命令对路径的要求。
例1:
javac的搜索根目录为当前目录,例如,在test下建立如下目录:aaa/bbb/ccc,再在test下建立一个文件:Main.java,内容如下:

view plaincopy to clipboardprint?
  1. package?aaa.bbb.ccc;??
  2. import?java.io.*;??
  3. ??
  4. public?class?Main?{??
  5. ????public?static?void?main?(String[]?args)?throws?IOException?{??
  6. ????????System.out.println("I?am?class?Main.");??
  7. ????????b.say();??
  8. ????}??
  9. ????static?B?b?=?new?B?();??
  10. }??
  11. ??
  12. class?B?{??
  13. ????public?void?say?()??
  14. ????{??
  15. ????????System.out.println("I?am?class?B.");??
  16. ????}??
  17. }??

在packageTest目录下编译:

$ javac Main.java

仍在packageTest目录下运行:

$ java Main

失败。因为Main类在包aaa.bbb.ccc中,java会在CLASSPATH(假设已经将当前目录:./加入到了CLASSPATH中)下找aaa/bbb/ccc/Main.class,当然找不到。实际上,即使把CLASSPATH设为./aaa/bbb/ccc,java仍然找不到Main,这里涉及到一个fully-qualified class name的概念,即,当给一个类打了包,类的名字就不再是原来的名字,必须加上包的名字,在本例子中,Main类被打在aaa/bbb/ccc包中后,其fully-qualified class name为aaa.bbb.ccc.Main。当然,这和将类打在默认包中时的情况不同,类打在默认包中时没有fully-qualified class name,也可以说其fully-qualified class name就是原生的类名。好了,再运行:

$ java aaa.bbb.ccc.Main

仍失败!错误提示说没有找到 main class,哦,对,原来是没把Main拷到aaa/bbb/ccc中去,拷进去后再运行:

$ java aaa.bbb.ccc.Main

仍失败!!错误提示说没有找到 main class,不知道为什么还会提示这个错误,其实错误原因是B.class放的位置不对由于class B和Main放在同一个翻译单元中,故编译器图方便直接把B.class放在了当前目录中,实际上class B也是aaa.bbb.ccc包中的成员,所以运行时java没有在这个包中找到class B,当把B.class拷到aaa/bbb/ccc目录下后再运行:

$ java aaa.bbb.ccc.Main

成功显示结果:

I am class Main.I am class B.

例2:
对Main.java做修改,把要使用的类B移出当前翻译单元:

view plaincopy to clipboardprint?
  1. package?aaa.bbb.ccc;??
  2. import?java.io.*;??
  3. ??
  4. public?class?Main?{??
  5. ????public?static?void?main?(String[]?args)?throws?IOException?{??
  6. ????????System.out.println("I?am?class?Main.");??
  7. ????????b.say();??
  8. ????}??
  9. ????static?B?b?=?new?B?();??
  10. }??

然后在packageTest下新建一个B.java:

view plaincopy to clipboardprint?
  1. package?aaa.bbb.ccc;??
  2. import?java.io.*;??
  3. public?class?B?{??
  4. ????void?say?()?{??
  5. ????????System.out.println("I?am?the?goddamn?B!");??
  6. ????}??
  7. }??

编译:

$ javac Main.java

失败。原因是javac没有找到symbol: class B,把B.java拷到aaa/bbb/ccc下后,编译成功,并在aaa/bbb/ccc下生成了B.class。原来javac在本翻译单元中找不到B后会去包aaa.bbb.ccc中找,所以package语句不止跟java有关,javac也要用它。实际上,javac需要的也是class文件,即javac发现import语句后,也要去CLASSPATH中去找编译时所需要的类,如果class文件存在,直接使用;如果不存在,对应的java源文件存在也行,这时,javac会先将B.java编译成B.class,这样Main中所需要的aaa.bbb.ccc.B就存在了,编译通过。因此,不论是java还是javac还是其它程序,只要其找的是class文件,就需要到CLASSPATH指定的目录中去找。如果CLASSPATH不设,默认为当前目录".",故即使echo出的$CLASSPATH什么也没有,它也是".",这一点比较奇怪。另外,目前还不清楚java的“库“放在哪,比如上面程序中的java.io.*,而且java怎么去找这些class,至少应该不是通过CLASSPATH。javac编译过程中寻找类名的顺序是定死的,这个顺序参见附记。
接下来在test中运行:

$ java aaa.bbb.ccc.Main

失败。忘记把Main.class拷到aaa/bbb/ccc中去了。拷过去以后在test中执行上面命令,结果为:

I am class Main.I am the goddamn B!

例3:
主要想明确一下javac搜索类型的顺序。
Main.java如例1:

view plaincopy to clipboardprint?
  1. package?aaa.bbb.ccc;??
  2. import?java.io.*;??
  3. ??
  4. public?class?Main?{??
  5. ????public?static?void?main?(String[]?args)?throws?IOException?{??
  6. ????????System.out.println("I?am?class?Main.");??
  7. ????????b.say();??
  8. ????}??
  9. ????static?B?b?=?new?B?();??
  10. }??
  11. ??
  12. class?B?{??
  13. ????public?void?say?()??
  14. ????{??
  15. ????????System.out.println("I?am?class?B.");??
  16. ????}??
  17. }??

另外还有B.java:

view plaincopy to clipboardprint?
  1. package?aaa.bbb.ccc;??
  2. import?java.io.*;??
  3. public?class?B?{??
  4. ????void?say?()?{??
  5. ????????System.out.println("I?am?the?goddamn?B!");??
  6. ????}??
  7. }??

这次两个class都放在aaa/bbb/ccc下,在packageTest中执行命令:

$ javac aaa/bbb/ccc/Main.java

在aaa/bbb/ccc下生成Main.class和B.class,然后运行:

$ java aaa.bbb.ccc.Main

结果为:

I am class Main.I am class B.

可见生成的B.class由Main.java中的class B生成,这体现了javac的一种搜索类型的顺序。

附记:
从《The Java Programming Language》中摘抄过来一段:
If your class declares a reference of type B(原话不是B,我只是接上面的例子说明)the compiler will search for the type in the following order:
1.The current type(貌似指A) including inherited types.
2.A nested type of the current type.
3.Explicitly named imported types (single type import).
4.Other thpes declared in the same package.
5.Implicitly named imported types (import on demand).

热点排行