组成程序包的类型称为程序包成员。
要从public包外部使用包成员,必须执行以下操作之一:
- 用其完全限定的名称引用该成员
- 导入包成员
- 导入成员的整个包
用包名来引用包成员
到目前为止,本教程中的大多数示例都通过简单名称(例如Rectangle和StackOfInts)来引用类型。如果您要编写的代码与该成员位于同一软件包中,或者已导入该成员,则可以使用该成员的简单名称。
但是,如果您尝试使用来自其他软件包的成员,但尚未导入该软件包,则必须使用成员的全限定名,其中包括软件包名称。这是上一个示例,在graphics包中声明的Rectangle类的完全限定名称。
graphics.Rectangle
您可以使用此限定名graphics.Rectangle来创建实例:
graphics.Rectangle myRect = new graphics.Rectangle();
完全限定名称可以不经常使用。但是,当重复使用名称时,重复输入名称将变得乏味,并且代码变得难以阅读。或者,您可以导入成员或其包,然后使用其简单名称。
导入包成员
要将特定成员导入当前文件,请在任何类型定义之前,在文件的开头放置一个import语句,但如果存在package,则在该语句之后。这是从上一部分中创建的graphics包中导入Rectangle类的方式。
import graphics.Rectangle;
现在,您可以通过其简单名称Rectangle来引用该类。
Rectangle myRectangle = new Rectangle();
如果仅使用graphics软件包中的几个成员,则此方法效果很好。但是,如果您从包中使用许多类型,则应导入整个包。
导入整个程序包
要导入特定程序包中包含的所有类型,请使用import带有星号(*)通配符的语句。
import graphics.*;
现在,您可以通过其简单名称来引用graphics包中的任何类或接口。
Circle myCircle = new Circle();Rectangle myRectangle = new Rectangle();
import语句中的星号只能用于指定包中的所有类,如下所示。它不能用于匹配包中类的子集。例如,以下代码与graphics包中以A开头的所有类都不匹配。
// does not workimport graphics.A*;
而且,它生成一个编译器错误。使用import语句,通常只导入一个包成员或整个包。
注意: 另一种不太常见的import形式允许您导入封闭类的公共嵌套类。例如,如果graphics.Rectangle类包含有用的嵌套类,例如Rectangle.DoubleWide和Rectangle.Square,则可以使用以下两个语句来导入Rectangle及其嵌套类。
import graphics.Rectangle;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.color,java.awt.font或者任何其它java.awt.xxxx的包。如果您打算使用中java.awt的类和其他类型,以及java.awt.color中的类和其他类型,则必须导入两个包及其所有文件:
import java.awt.*;import java.awt.color.*;
名字歧义
如果一个包中的成员与另一个包中的成员共享其名称,并且两个包都已导入,则必须使用其限定名称来引用每个成员。例如,graphics程序包定义了一个名为Rectangle的类。java.awt软件包还包含一个Rectangle类。如果graphics与java.awt已经同时导入,下面是模糊的。
Rectangle rect;
在这种情况下,您必须使用成员的全限定名来准确指示您想要的Rectangle类。例如,
graphics.Rectangle rect;
静态导入语句
在某些情况下,您需要经常访问一两个类的静态final字段(常量)和静态方法。一遍又一遍地加上这些类的名称可能会导致代码混乱。静态导入语句(static import statement)给你一个方法,来导入常量和静态方法,这样你就不需要使用类的名称的前缀。java.lang.Math类定义了PI恒定和许多静态方法,包括用于计算正弦,余弦,正切,平方根,最大值,最小值,指数和更多的方法。例如,
public static final double PI= 3.141592653589793;public static double cos(double a){...}
通常,要使用另一个类中的这些对象,请在类名前添加前缀,如下所示。
double r = Math.cos(Math.PI * theta);
您可以使用static import语句来导入java.lang.Math的静态成员,这样就无需在类名之前添加前缀Math。静态成员Math可单独输入:
import static java.lang.Math.PI;
或作为一个组:
import static java.lang.Math.*;
导入静态成员后,无需限定名称,即可使用它们。例如,先前的代码片段将变为:
double r = cos(PI * theta);
显然,您可以编写自己的类,这些类包含经常使用的常量和静态方法,然后使用静态import语句。例如,
import static mypackage.MyConstants.*;
注意: 非常谨慎地使用静态导入。过度使用静态导入会导致代码难以阅读和维护,因为代码的读者不会知道哪个类定义了特定的静态对象。通过正确使用静态导入,可以消除类名重复,从而使代码更具可读性。
