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