想要将一个类放入包中,就必须将包的名字放在源文件的开头,包中定义类的代码之前。例如,例4-7中的文件Employee.java开头是这样的:
- package com.horstmann.corejava;
- public class Employee
- {
- ....
- }
如果没有在源文件中放置package语句,这个源文件中的类就被放置在一个默认包(default package)中。默认包是一个没有名字的包。在此之前,我们定义的所有类都在默认包中。
将包中的文件放到与完整的包名匹配的子目录中。例如,com.horstmann.corejava包中的所有源文件应该被放置在子目录com\horstmann\corejava(Windows中com\horstmann\corejava)中。编译器将类文件也放在相同的目录结构中。
例4-6和例4-7中的程序分放在两个包中:PackageTest类放置在默认包中;Employee类放置在com.horstmann.corejava包中。因此,Employee.class文件必须包含在子目录com\horstmann\corejava中。换句话说,目录结构如下所示:
- 基目录
- PackageTest.java
- PackageTest.class
- com\
- horstmann\
- corejava\
- Employee.java
- Employee.class
想要编译这个程序,只需改变基目录,并运行命令
- javac PackageTest.java
编译器就会自动地查找文件com/horstmann/corejava/Employee.java并进行编译。
下面看一个更加实际的例子。在这里不使用默认包,而是将类分别放在不同的包中(com.horst-mann.corejava和com.mycompany)。
- 基目录
- com/
- horstmann/
- corejava/
- Employee.java
- Employee.class
- mycompany
- PayrollApp.java
- PayrollApp.class
需要注意,编译器对文件(带有文件分隔符和扩展名.java的文件)进行操作。而java解释器加载类(带有.分隔符)。
警告:编译器在编译源文件的时候不检查目录结构。例如,假定有一个源文件开头有下列语句:
package com.mycompany;
即使这个源文件没有在子目录com/mycompany下,也可以进行编译。如果它不依赖于其他包,就不会出现编译错误。但是,最终的程序将无法运行,这是因为虚拟机找不到类文件。
例4-6 PackageTest.java
- import com.horstmann.corejava.*;
- // the Employee class is defind in that package
- import static java.lang.System.*;
- /**
- * This program demonstrates the use of packages.
- * @ author Wcg
- * @ version 1.01 2012-11-19
- */
- public class PackageTest
- {
- public static void main(String[] args)
- {
- // because of the import statement, we don't have to use com.horstmann.corejava.Employee here
- Employee harry = new Employee("Harry Hacker", 50000, 1989, 10, 1);
- harry.raiseSalary(5);
- // because of the static import statement, we don't have to use System.out here
- out.println("name = " + harry.getName() + ", salary = " + harry.getSalary());
- }
- }
例4-7 Employee.java
- package com.horstmann.corejava;
- // the classes in this file are part of this package
- import java.util.*;
- //import statements come after the package statement
- /**
- * @version 1.01 2012-11-19
- * @author Wcg
- */
- public class Employee
- {
- public Employee(String aName, double aSalary, int aYear, int aMonth, int aDay)
- {
- name = aName;
- salary = aSalary;
- GregorianCalendar calendar = new GregorianCalendar(aYear, aMonth - 1, aDay);
- // GregorianCalendar uses 0 for January
- hireDay = calendar.getTime();
- }
- public String getName()
- {
- return name;
- }
- public double getSalary()
- {
- return salary;
- }
- public Date getHireDay()
- {
- return hireDay.clone();
- }
- public void raiseSalary(double byPercent)
- {
- double raise = salary * byPercent / 100;
- salary = salary + raise;
- }
- private String name;
- private double salary;
- private Date hireDay;
- }