Packages
A package is the Java version of a library.
A package refers simply to a group of related class files
in the same directory
and having in each class file a package
directive (Java statements
only occur within a class definition) with that directory name
at the top of the file.
For example, say that we put the files TestA.java
and TestB.java
into the directory mypack,
which is a subdirectory of myApps.
So on a MS Windows platform the file path looks like
c:\myApps\mypack\TestA.java
and
c:\myApps\mypack\TestB.java.
At the top of each file we put the statement
package
mypack;
as shown in the following code:
We can illustrate how to use a package with TestAB.java
which we put in the next directory above that of the package mypack.
|
myApps/TestABApplet.java
(Output goes to browser's Java
console.)
|
public
class
TestABApplet extends java.applet.Applet
{
public void init
() {
mypack.TestA testa = new
mypack.TestA (4);
mypack.TestB testb = new
mypack.TestB (31.3);
System.out.println("Prod = " + (testa.i
* testb.x));
}
// Paint message in Applet window.
public void paint(java.awt.Graphics g) {
g.drawString ("TestABApplet",20,20);
}
}
|
|
From the command line in the directory myApps,
the compilation of TestAB.java:
myApps>
javac TestAB.java
will also lead to the compilation of the files in mypack.
The compiler looks for the TestA
and TestB class
definitions using the combination of the package and class names
mypack.TestA
testa and mypack.TestB.
The "." acts in this case like the slash line directory
name separator in DOS or Unix.
In this case the compiler will look for a sub-directory named
mypack
in the current directory holding TestAB.java.
When the compiler finds the files and they have not yet been
compiled, it will do the compilation.
You can also compile the package files directly but the compilation
must occur from the higher directory, as in.
myApps>
javac mypack\TestAB.java
(If you try to compile from in the mypack
directory, the compiler will say it cannot find the files.)
So a directory browser shows a file and directory organization
as follows:
Just as a directory can contain sub-directories, a package can
contain sub-packages. For example, here we create add extrapack
as a sub-package of mypack.
The class definition for TestC
belongs to the package mypack.extrapack,
as indicated here by the package
statement at the top of the file:
Note: By convention,
package names begin with a lowercase letter, while classes begin
with an uppercase letter.
Namespace
In addition to organizing classes in a clearly defined manner,
packages also prevent name collisions. That is, if you
use classes from other sources, it is inevitable that eventually
duplicate class names will occur. If they are in different packages,
however, this is not a problems since their full package
names would differ.
Of course, it's also possible that two packages from different
sources could also have the same names. An ingenious naming convention
promulgated by Sun from the earliest days of Java is to name packages
based on a company's internet domain name with the order of the
names reversed. Since domain names are unique, package names based
on domain names are completely under the control of the company
that owns that domain name. Thus our companies ABC and XYZ would
probably name their packages com.abc
and com.xyz,
respectively.
import
If a program needed to create an instance of TestC,
it can explicitly give the full package path name, also referred
to as the the "fully qualified" name:
mypack.extrapack.TestC testc = new
mypack.extrapack.TestC();
An exception to this rule holds for all the classes in the standard
java.lang
package. Thus, whenever we use the Float class, for instance,
we merely use something like
Float
someFloat = new Float (3.14);
For all other classes, however, the fully qualified names must
be specified in some way. There are nearly 3000 classes in the
135 packages in the J2SE 1.4.2 standard class library (over 3000
classes in 165 packages in J2SE 5.0). Commercial class libraries
that you might use add many more packages.
Such long names obvious become unwieldy when a program involves
many different classes from many different packages. The Java
compiler allows instead for a short cut.
The import
directive tells the compiler where to look for the class definitions
when it comes upon a class that it cannot find in the default
java.lang
package. So, for example, in the class definition below for TestABC,
the import statements
import
mypack.*;
import mypack.extrapack.*;
import java.applet.*;
indicate that classes can be found in the mypack and mypack.extrapack
packages and also that the Applet
class can be found in the java.applet
package.
|
myApps/TestABCApplet.java
(Output goes to browser's Java
console.)
|
import
java.applet.Applet;
import
mypack.*;
import mypack.extrapack.*;
public
class
TestABCApplet extends Applet
{
public static void
init (String [] arg) {
TestA testa = new
TestA (4);
TestB testb = new
TestB (31.3);
if( testc.flag)
System.out.println
("testa.i = "+testa.i);
else
System.out.println
("testa.x = "+testb.x);
}
//
Paint message in Applet window.
public void paint(java.awt.Graphics g) {
g.drawString ("TestABACpplet",20,20);
}
}
|
|
The first import statement gives the full package path name
for the Applet
class in the packages included with the standard JVM. Then when
the compiler sees just Applet
in the class definition title, it will know where to find it.
In the next two import statements, we see the "*"
wildcard character used for the classes in the mypack
and mypack.extrapack
packages. This indicates that these packages hold multiple classes
and the compiler should look here if it cannot find a class
in the core packages.
The wildcard only applies to classes, not to sub-packages.
That is, mypack.*
only refers to the classes in the package, not to the sub-directory
extrapack.
You must import each package name separately.
If the packages that you import happened to have two classes
with the same name, to use one of them you will need to give
the fully qualified name so that the compiler will know which
of these classes you want to use.
Notes
Note 1: C/C++ programmers usually
assume that an import
statement brings code into the .class
bytecode files in a similar manner as the include
statements in C/C++. However, that is not the case. An import
statement simply provides an address where the compiler can
look for class definitions.
We will also point out that Java is a so-called late binding
object language, which means that it does not load class definitions
until they are needed during processing. In fact, while a program
is running it can dynamically load a class that was never mentioned
in the source code. (For example, the class name could be read
in from a file.)
Note 2 : To
insure the uniqueness of package names, Sun proposes that the
package name include your domain name (if you own one). For example,
com.mycompany.mypack.Test;
indicates that the Test
class file belongs to the the mypack
package owned by mycompany.com.
Note 3: By convention
package names begin with a lowercase letter while class names
begin with an uppercase letter. In fact, package names are often
completely lower case, as is true of all but 28 of the 135 packages
of J2SE 1.4.2. (Those 28 packages with uppercase characters are
all part of the CORBA system in Java which we discuss in Chapter
19 and which use uppercase names for consistency with the
CORBA naming conventions.)
Note
4: If a file does not explicitly
belong to a package, then it is put into the default unnamed
package, which is maintained internally by the JVM.
However, for all but small test and demonstration programs you
should put your classes into packages so as to avoid name collisions,
avoid access to your class internals by other classes (see access
rules), and to maintain neat class organisation.
We did not put most of our demonstration programs
here into packages because we wanted to allow readers to download
codes and quickly compile and run them without needing to set
up the appropriate package subdirectories.