理解类路径是什么意思?如何运用包?

246 阅读3分钟

昨天的文章中简单的介绍了包,今天就包的应用,在介绍运用包的例子之前,关于类路径环境变量的简单讨论是必要的。当包从访问控制和名称-空间-冲突中解决很多问题时,在编译和运行程序时它们导致某些古怪的难点。

这是因为Java编译器考虑的特定位置作为包层次的根被类路径(CLASSPATH)控制。直到现在,你在同样的未命名的默认包中保存所有的类。这样做允许你仅仅通过在命令行键入类名编译源文件和运行Java解释器,并得到结果。这种情况下它还会工作是因为默认的当前工作目录(.)通常在类路径环境变量中为Java运行时间默认定义。

然而,当有包参与时,事情就不这么简单。下面是原因。假设你在一个test包中创建了一个名为PackTest 的类。

因为你的目录结构必须与包相匹配,你创建一个名为test的目录并把PackTest.java装入该目录。然后使test 成为当前目录并编译PackTest.java。这导致PackTest.class被存放在test目录下。当你试图运行PackTest时,java 解释器报告一个与“不能发现PackTest类”相似的错误消息。这是因为该类现在被保存在test包中。不再能简单用PackTest来引用。必须通过列举包层次来引用该类。引用包层次时用逗号将包名隔开。该类现在必须叫test.PackTest。

然而,如果你试图用test.PackTest,你将仍然收到一个与“不能发现test/PackTest类”相似的出错消息。

仍然收到错误消息的原因隐藏在类路径变量中。记住,类路径设置顶层类层次。问题在于在当前工作目录下不存在test子目录,因为你是工作在test目录本身。

在这个问题上你有两个选择:改变目录到上一级然后用java test.PackTest,或者在类路径环境变量增加你的开发类层次结构的顶层。然后可以用java test.PackTest,Java将发现正确的.class文件。例如,如果你的源代码在目录C:\myjava下,那么设置类路径为:

.;C:\myjava;C:\java\classes

一个简短的包的例子 记住前面的讨论,试试下面简单的包:

// A simple package 
package MyPack; 
class Balance { 
 String name; 
 double bal; 
 Balance(String n, double b) { 
 name = n; 
 bal = b; 
 } 
 void show() { 
 if(bal<0) 
 System.out.print("--> "); 
 System.out.println(name + ": $" + bal); 
 } 
} 
class AccountBalance { 
 public static void main(String args[]) { 
 Balance current[] = new Balance[3]; 
 current[0] = new Balance("K. J. Fielding", 123.23); 
 current[1] = new Balance("Will Tell", 157.02); 
 current[2] = new Balance("Tom Jackson", -12.33); 
 for(int i=0; i<3; i++) current[i].show(); 
 } 
}

称该文件名为 AccountBalance.java,把它存放在MyPack目录中。 接着,编译文件。确信结果文件.class同样在MyPack 目录中。然后用下面的命令行执行AccountBalance 类:

java MyPack.AccountBalance

记住,当你执行该命令时你必须在MyPack的上级目录,或者把类路径环境变量设置成合适的值。

如上所述,AccountBalance现在是MyPack包的一部分。这意味着它不能自己执行。也就是说你不能用下面的命令行:

java AccountBalance

AccountBalance必须和它的包名一起使用。