在Java中使用包,以防止命名冲突,控制访问,使搜索/定位和类,接口,枚举和注解的使用更容易,等等。
一个包可以被定义为相关类型(类,接口,枚举和注解)提供访问保护和命名空间管理的分组。
一些在Java中现有的包是:
java.lang - 捆绑的基础类
java.io - 用于输入,输出功能的类捆绑在这个包
程序员可以定义自己的包捆绑组的类/接口等,这是一个很好的做法来实现相关的类,使程序员可以很容易地确定的类,接口,枚举,注释都是相关的。
由于包创建一个新的命名空间不会有与其他包名称的任何名称冲突。使用包,它更容易提供访问控制,它也更容易找到相关的类。
创建一个包的时候,应该选择的包的名称,并把包语句具有该名称在每个源文件的顶部,包含要在包中包括的类,接口,枚举和注解类型。
package语句必须是源文件中的第一行。只能有各一个源文件中package语句,并且它适用于所有类型的文件中。
如果不使用package语句则类,接口,枚举和注释类型将被放入一个未命名的包。
让我们看看它创建了一个名为 animals 包的示例。它是用小写名称,以避免与类,接口名称的任何冲突常见的做法。
把一个接口放在包animals:
/* File name : Animal.java */ package animals; interface Animal { public void eat(); public void travel(); }
现在,把一个实现在同一个 animals 包中:
package animals; /* File name : MammalInt.java */ public class MammalInt implements Animal{ public void eat(){ System.out.println("Mammal eats"); } public void travel(){ System.out.println("Mammal travels"); } public int noOfLegs(){ return 0; } public static void main(String args[]){ MammalInt m = new MammalInt(); m.eat(); m.travel(); } }
现在,编译这两个文件,并把它们放到一个子目录叫做 animals 并尝试运行如下:
$ mkdir animals $ cp Animal.class MammalInt.class animals $ java animals/MammalInt Mammal eats Mammal travels
如果一个类希望使用另一个类在同一包中,包的名称并不需要被使用。在同一个包中的类发现对方没有任何特殊的语法。
在这里,一个叫Boss类添加到已包含Employee的payroll 包。然后,Boss可以参考Employee类,而不使用前缀工资,主要表现如以下Boss类。
package payroll; public class Boss { public void payEmployee(Employee e) { e.mailCheck(); } }
如果Boss类不在payroll 包会发生什么?Boss类必须然后使用下列方法之一来引用类在不同的包。
可以使用类的完全限定名。例如:
payroll.Employee
包可以使用import关键字和通配符(*)导入。例如:
import payroll.*;
类本身可以使用import关键字导入。例如:
import payroll.Employee;
注:一个类文件可以包含任意数量的导入语句。 package语句之后,并在类声明之前的import语句必须出现。
当一个类被放置在一个包中发生两个主要结果:
包的名称将成为类的名称的一部分,正如我们在上一节刚刚讨论。
包的名称必须与相应的字节码所在的目录结构相匹配。
下面是简单的管理中的Java文件的方式:
把源代码的类,接口,枚举或注释类型在一个文本文件,其名称的类型,其扩展名是 .java。例如:
// File Name : Car.java package vehicle; public class Car { // Class implementation. }
现在,把源文件中的目录,其名称反映了类所属的包的名称:
..../vehicle/Car.java
现在,合格的类名和路径名会是如下:
类名称 -> vehicle.Car
路径名称 -> vehicle/Car.java (in windows)
一般情况下,一家公司使用其反向的Internet域名,其包名。例:某公司的Internet域名是apple.com,那么它的所有包名就开始就可以为 com.apple。包名称的每个组件对应一个子目录。
例如:公司有包含一个Dell.java源文件com.apple.computers包,将它包含在一系列这样的子目录:
..../com/apple/computers/Dell.java
在编译时,编译器会为它定义的每个类,接口和枚举不同的输出文件。输出文件的基本名称是类型的名称,及其扩展名是 .class
例如:
// File Name: Dell.java package com.apple.computers; public class Dell{ } class Ups{ }
现在,编译该文件使用-d选项,如下所示:
$javac -d . Dell.java
这将使编译后的文件如下所示:
./com/apple/computers/Dell.class ./com/apple/computers/Ups.class
可以导入所有已定义的类或接口 /com/apple/computers/ 如下:
import com.apple.computers.*;
像 .java源文件,编译后的 .class文件应该是在一个系列,反映包名的目录。然而,类文件并不一定是相同的 .java源文件路径。可以单独安排源文件和类目录,如:
<path-one>/sources/com/apple/computers/Dell.java <path-two>/classes/com/apple/computers/Dell.class
通过这样做,可以给classes目录到其他程序员不透露源代码。还需要管理这种方式的源文件和类文件,使编译器和Java虚拟机(JVM)可以找到所有程序使用的类型。
完整路径的classes目录,<path-two>/类,被称为类路径,并设置与CLASSPATH系统变量。无论是编译器和JVM通过将包名到类路径构建的路径 .class 文件。
<path-two>/classes是类路径和包名是com.apple.computers,那么编译器和JVM将寻找在<path-two>/classes/com/apple/compters 文件中的 .class文件。
类路径可能包括几个路径。多条路径应该用分号(Windows)或冒号(UNIX)分隔。默认情况下,编译器和JVM搜索当前目录,并包含了Java平台的类,使这些目录会自动在类路径的JAR文件。
要显示当前的CLASSPATH变量,使用Windows和UNIX(Bourne shell的)下面的命令:
在Windows -> C:/> set CLASSPATH
在UNIX -> % echo $CLASSPATH
要删除CLASSPATH变量的当前内容,使用:
在 Windows -> C:/> set CLASSPATH=
在 UNIX -> % unset CLASSPATH; export CLASSPATH
要设置CLASSPATH变量:
在 Windows -> set CLASSPATH=C:/users/jack/java/classes
在 UNIX -> % CLASSPATH=/home/jack/java/classes; export CLASSPATH