组成程序包的类型称为程序包成员
要从public包外部使用包成员,必须执行以下操作之一:

  • 用其完全限定的名称引用该成员
  • 导入包成员
  • 导入成员的整个包

每种方法都适用于不同的情况,如以下各节所述。

用包名来引用包成员

到目前为止,本教程中的大多数示例都通过简单名称(例如RectangleStackOfInts)来引用类型。如果您要编写的代码与该成员位于同一软件包中,或者已导入该成员,则可以使用该成员的简单名称。
但是,如果您尝试使用来自其他软件包的成员,但尚未导入该软件包,则必须使用成员的全限定名,其中包括软件包名称。这是上一个示例,在graphics包中声明的Rectangle类的完全限定名称。

  1. graphics.Rectangle

您可以使用此限定名graphics.Rectangle来创建实例:

  1. graphics.Rectangle myRect = new graphics.Rectangle();

完全限定名称可以不经常使用。但是,当重复使用名称时,重复输入名称将变得乏味,并且代码变得难以阅读。或者,您可以导入成员或其包,然后使用其简单名称。

导入包成员

要将特定成员导入当前文件,请在任何类型定义之前,在文件的开头放置一个import语句,但如果存在package,则在该语句之后。这是从上一部分中创建的graphics包中导入Rectangle类的方式。

  1. import graphics.Rectangle;

现在,您可以通过其简单名称Rectangle来引用该类。

  1. Rectangle myRectangle = new Rectangle();

如果仅使用graphics软件包中的几个成员,则此方法效果很好。但是,如果您从包中使用许多类型,则应导入整个包。

导入整个程序包

要导入特定程序包中包含的所有类型,请使用import带有星号(*)通配符的语句。

  1. import graphics.*;

现在,您可以通过其简单名称来引用graphics包中的任何类或接口。

  1. Circle myCircle = new Circle();
  2. Rectangle myRectangle = new Rectangle();

import语句中的星号只能用于指定包中的所有类,如下所示。它不能用于匹配包中类的子集。例如,以下代码与graphics包中以A开头的所有类都不匹配。

  1. // does not work
  2. import graphics.A*;

而且,它生成一个编译器错误。使用import语句,通常只导入一个包成员或整个包。


注意: 另一种不太常见的import形式允许您导入封闭类的公共嵌套类。例如,如果graphics.Rectangle类包含有用的嵌套类,例如Rectangle.DoubleWideRectangle.Square,则可以使用以下两个语句来导入Rectangle及其嵌套类。

  1. import graphics.Rectangle;
  2. import graphics.Rectangle.*;

请注意,第二个import语句将不会导入Rectangle

另一种不太常见的import形式,静态import语句,将在本节结束讨论。


为了方便起见,Java编译器会为每个源文件自动导入两个完整的软件包:(1)java.lang软件包和(2)当前软件包(当前文件的软件包)。

程序包的明显层次结构

最初,程序包看起来是分层的,但实际上不是。例如,Java API包括一个java.awt包,一个java.awt.color包,一个java.awt.font包,以及许多其他以java.awt开头的包。但是,java.awt.color程序包,java.awt.font程序包和其他java.awt.xxxx程序包不包括java.awt程序包中。前缀java.awt(Java抽象窗口工具包)用于许多相关的软件包,以使关系显而易见,但不显示包含关系。
java.awt.*导入所有在java.awt包的类型,但它不会导入 java.awt.colorjava.awt.font或者任何其它java.awt.xxxx的包。如果您打算使用中java.awt的类和其他类型,以及java.awt.color中的类和其他类型,则必须导入两个包及其所有文件:

  1. import java.awt.*;
  2. import java.awt.color.*;

名字歧义

如果一个包中的成员与另一个包中的成员共享其名称,并且两个包都已导入,则必须使用其限定名称来引用每个成员。例如,graphics程序包定义了一个名为Rectangle的类。java.awt软件包还包含一个Rectangle类。如果graphicsjava.awt已经同时导入,下面是模糊的。

  1. Rectangle rect;

在这种情况下,您必须使用成员的全限定名来准确指示您想要的Rectangle类。例如,

  1. graphics.Rectangle rect;

静态导入语句

在某些情况下,您需要经常访问一两个类的静态final字段(常量)和静态方法。一遍又一遍地加上这些类的名称可能会导致代码混乱。静态导入语句(static import statement)给你一个方法,来导入常量和静态方法,这样你就不需要使用类的名称的前缀。
java.lang.Math类定义了PI恒定和许多静态方法,包括用于计算正弦,余弦,正切,平方根,最大值,最小值,指数和更多的方法。例如,

  1. public static final double PI
  2. = 3.141592653589793;
  3. public static double cos(double a)
  4. {
  5. ...
  6. }

通常,要使用另一个类中的这些对象,请在类名前添加前缀,如下所示。

  1. double r = Math.cos(Math.PI * theta);

您可以使用static import语句来导入java.lang.Math的静态成员,这样就无需在类名之前添加前缀Math。静态成员Math可单独输入:

  1. import static java.lang.Math.PI;

或作为一个组:

  1. import static java.lang.Math.*;

导入静态成员后,无需限定名称,即可使用它们。例如,先前的代码片段将变为:

  1. double r = cos(PI * theta);

显然,您可以编写自己的类,这些类包含经常使用的常量和静态方法,然后使用静态import语句。例如,

  1. import static mypackage.MyConstants.*;

注意: 非常谨慎地使用静态导入。过度使用静态导入会导致代码难以阅读和维护,因为代码的读者不会知道哪个类定义了特定的静态对象。通过正确使用静态导入,可以消除类名重复,从而使代码更具可读性。