在程序设计中,把相关的程序段组合起来经常是很有益的.在Java中,这是通过使用包来实现的.包服务于两个项目:首先,他提供了把相关的程序段组织成一个单元的机制,在包中定义的类必须通过他们的包来访问.这样,包就提供了一种命名类的集合的途径.其次,包还参与了Java的访问控制机制.包中定义的类可以声明为包所私有,使包外的代码无法访问.这样,包就提供了一种能够封装类的方式.让我们更进一步了解每一个特性.
一般而言,当命名类的时候,是从命名空间(namespace)中分配一个名字.命名空间定义了一个声明性的区域.在Java中,同一个命名空间的两个类不能使用相同的名称.这样,在一个给定的名称空间中,每一个类名必然是唯一的.但是随着程序的增大和默认的名称空间变得拥挤,就出现了问题.在大型程序中,为每一个类找到唯一的名字可能就困难了.更进一步而言,就是必须避免名字与同一个项目下运行的其他程序创建的代码以及Java类库相互冲突.包就是解决这些问题的办法,因为他提供了一种为命名空间分区的方法.当在包定义一个类时,该包的名字将会附加到每一个类上,这样就避免了与其他包中具有相同名称的类发生名称冲突.
由于包通常包含的是相关的类,因此Java对包中的代码定义了特殊的访问权限.在一个包中,可以定义代码使他可以被同一个包中的其他代码访问,但不能被该包外的代码访问.这样就创建一个相关类的独立的组,并且保证了其操作是私有的.
1.定义包
Java中的所有类都属于某个包.当没有指定package语句时,使用默认的或全局的包.而且,默认包没有名字,这就使得默认包是透明的.虽然对于简短的示例程序而言默认包很适合,但对实际应用程序而言是不够的.大多数情况下,应该为代码定义一个或多个包.
要创建一个包,需要在Java源文件的顶部使用package命令,这样在该文件中声明的类就会属于指定的包.由于一个包定义了一个名称空间,因此放入该文件中的类的名字就成为该包的名称空间的一部分.
下面是package语句的一般格式:
package pkg;
这里,pkg是包的名字.例如,下面的语句创建了一个名为mypack的包:
package mypack;
Java使用文件系统来管理包,每一个包都保存在自己的目录中.例如,所声明的属于mypack的任何类的.class文件都必须保存在名为mypack的目录中.
像Java的其他元素一样,包名也是区分大小写的.这就意味着存储包的目录的名字必须和包的名字完全一致.
多个文件中可能包括相同的package语句.package语句只是指定了在一个文件中定义的类属于哪一个包,他并不排除在同一个包含其他文件中的其他类.大多数实际应用中的包跨越了许多文件.
可以创建一个包层次结构.为此,只需使用逗号把每一个包和位于其上的包区分开来即可.下面是多层结构包语句的一般形式:
package pack1.pack2.pack3;
当然,必须创建目录来支持所创建的包层次结构.例如:
package alpha.beta.gamma;
必须存储在…/alpha/beta/gamma中,其中的…指定通项特定的目录的路径.
2.寻找包和CLASSPATH
正如刚才解释的那样,包是由目录镜像的.这提出了一个重要的问题:Java的运行时系统如何知道哪里寻找你所创建的包呢?答案有3个:首先,默认情况下,Java的运行时系统使用当前的工作目录作为他的起点.这样,如果你的包位于在当前目录的子目录中,就能找到他.其次,可以通过设定CLASSPATH环境变量来指定一个或多个目录路径.最后,可以在java或javac中使用classpath选项来指定类的路径.
例如,考虑下面的包声明:
package mypack
为了让程序找到mypack,必须具备下面的三个条件之一:程序从mypack紧上方的目录中执行,或者把CLASSPATH设置为包含指向的mypack的路径,或者在通过java运行程序时使用 -classpath选项指定mypack的路径.
3.一个简短的包示例
记住先前有关讨论,试验以下这个简短的包示例.创建了一个简单的test类,包含在一个名为test的包中:
package test; public class test { public void show() { System.out.println("test package - test"); } }
—
package javaTest; import test.test; public class test2 { // @param args public static void main(String args[]) { test t = new test(); t.show(); System.out.println(t.toString()); } }