6.3. Packages and Compilation Units
A
package
is a
6.3.1. Compilation UnitsThe source code for a Java class is organized into compilation units . A simple compilation unit contains a single class definition and is named for that class. The definition of a class named MyClass , for instance, could appear in a file named MyClass.java . For most of us, a compilation unit is just a file with a .java extension, but theoretically in an integrated development environment, it could be an arbitrary entity. For brevity, we'll refer to a compilation unit simply as a file. The division of classes into their own files is important because the Java compiler assumes much of the responsibility of a make utility. The compiler relies on the names of source files to find and compile dependent classes. It's possible to put more than one class definition into a single file, but there are some restrictions we'll discuss shortly. A class is declared to belong to a particular package with the package statement. The package statement must appear as the first statement in a compilation unit. There can be only one package statement, and it applies to the entire file:
package mytools.text;
class TextComponent {
...
}
In this example, the class TextComponent is placed in the package mytools.text . 6.3.2. Package Names
Package names are
6.3.3. Class VisibilityBy default, a class is accessible only to other classes within its package. This means that the class TextComponent is available only to other classes in the mytools.text package. To be visible elsewhere, a class must be declared as public :
package mytools.text;
public class TextEditor {
...
}
The class
TextEditor
can now be referenced
By hiding unimportant or extraneous classes, a package builds a
subsystem
that has a
Figure 6.6. Packages and class visibility
Figure 6-6 shows part of the hypothetical mytools.text package. The classes TextArea and TextEditor are declared public so that they can be used elsewhere in an application. The class TextComponent is part of the implementation of TextArea and is not accessible from outside of the package. 6.3.4. Importing Classes
Classes within a package can refer to each other by their simple names. However, to locate a class in another package, we have to be more specific. Continuing with the previous example, an application can refer directly to our editor class by its
fully qualified name
of
mytools.text.TextEditor
. But we'd quickly grow
Like a package statement, an import statement applies to the entire compilation unit. Here's how you might use an import statement:
package somewhere.else;
import mytools.text.TextEditor;
class MyClass {
TextEditor editBoy;
...
}
As shown in this example, once a class is imported, it can be referenced by its simple name throughout the code. It is also possible to import all the classes in a package using the * wildcard notation: import mytools.text.*; Now we can refer to all public classes in the mytools.text package by their simple names.
Obviously, there can be a problem with importing classes that have conflicting names. The compiler
Other than the potential for naming conflicts, there's no penalty for importing many classes. Java doesn't carry extra baggage into the compiled class files. In other words, Java class files don't contain information about the imports; they only reference classes actually used in them.
One note about conventions: in our efforts to keep our examples short we'll sometimes import entire packages (.*) even when we use only a class or two from it. In practice, it's usually better to be specific when possible and list individual, fully qualified class imports if there are only a few of them. Some people (
6.3.4.1 The unnamed package
A class that is defined in a compilation unit that doesn't specify a package
6.3.4.2 Static importsThe static import facility is new in Java 5.0. Using a variation of the import statement you can import static members of a class into the namespace of your file so that you don't have to qualify them when you use them. The best example of this is in working with the java.lang.Math class. With static import, we can get an illusion of built-in math "functions" and constants like so:
import static java.lang.Math.*;
// usage
double circumference = 2 * PI * radius;
double length = sin( theta ) * side;
int bigger = max( a, b );
int positive = abs( num );
This example imports all of the static members of the java.lang.Math class. We can also import individual members by name:
import static java.awt.Color.RED;
import static java.awt.Color.WHITE;
import static java.awt.Color.BLUE;
// usage
setField( BLUE );
setStripe( RED );
setStripe( WHITE );
To be precise, these static imports are importing a name, not a specific member into the namespace of our file. For example, importing the name "foo" would bring in any constants named foo as well as any methods named foo( ) in the class. Static imports are compelling and make life easier in Java 5.0. Using them too much, however, could quickly make your code difficult to read. |