Section 4.5
Toolboxes, API's, and Packages
AS COMPUTERS AND THEIR USER INTERFACES
have become easier to use, they have also become more complex
for programmers to deal with. You can write programs for a
simple console-style user interface using just a few subroutines that
write output to the console and read the user's
typed replies. A modern graphical user interface, with windows,
buttons, scroll bars, menus, text-input boxes, and so on,
might make things easier for the user. But it forces the
programmer to cope with a hugely expanded array of possibilities.
The programmer sees this increased complexity in the form of
great numbers of subroutines that are provided for managing
the user interface, as well as for other purposes.
Someone who wants to program for Macintosh computers -- and
to produce programs that look and behave the way users expect
them to -- must deal with the Macintosh Toolbox, a collection of
well over a thousand different subroutines. There are routines
for opening and closing windows, for drawing geometric figures
and text to windows, for adding buttons to windows, and for
responding to mouse clicks on the window. There are other routines
for creating menus and for reacting to user selections from menus.
Aside from the user interface, there are routines for opening files
and reading data from them, for communicating over a network,
for sending output to a printer, for handling communication
between programs, and in general for doing all the standard things
that a computer has to do. Windows 98 and Windows 2000 provide
their own sets of subroutines for programmers to use,
and they are quite a bit different from the subroutines used
on the Mac.
The analogy of a "toolbox" is a good one to keep
in mind. Every programming project involves a mixture of
innovation and reuse of existing tools. A programmer is given
a set of tools to work with, starting with the set of basic tools
that are built into the language: things like variables, assignment
statements, if statements, and loops. To these, the programmer
can add existing toolboxes full of routines that have already
been written for performing certain tasks. These tools, if they
are well-designed, can be used as true black boxes: They can
be called to perform their assigned tasks without worrying about
the particular steps they go through to accomplish those tasks.
The innovative part of programming is to take all these tools
and apply them to some particular project or problem (word-processing,
keeping track of bank accounts, processing image data from a
space probe, Web browsing, computer games,...). This is called
applications programming.
A software toolbox is a kind of black box, and it
presents a certain interface to the programmer.
This interface is a specification of what routines are in
the toolbox, what parameters they use, and what tasks they
perform. This information constitutes the API, or
Applications Programming Interface,
associated with the toolbox. The Macintosh API is a specification
of all the routines available in the Macintosh Toolbox.
A company that makes some hardware device -- say a card for
connecting a computer to a network -- might publish an API for
that device consisting of a list of routines that programmers
can call in order to communicate with and control the device.
Scientists who write a set of routines for doing some kind of
complex computation -- such as solving "differential
equations", say -- would provide an API to allow others
to use those routines without understanding the details of the
computations they perform.
The Java programming language is supplemented by a large,
standard API.
You've seen part of this API already, in the
form of mathematical subroutines such as Math.sqrt(),
the String data type and its associated routines,
and the System.out.print() routines. The standard
Java API includes routines for working with graphical user
interfaces, for network communication, for reading and
writing files, and more. It's tempting
to think of these routines as being built into the Java
language, but they are technically subroutines that have
been written and made available for use in Java programs.
Java is platform-independent. That is, the same program
can run on platforms as diverse as Macintosh, Windows,
UNIX, and others. The same Java API must work on all these
platforms. But notice that it is the interface
that is platform-independent; the implementation
varies from one platform to another. A Java system on a particular
computer includes implementations of all the standard API routines.
A Java program includes only calls to those
routines. When the Java interpreter executes a program and
encounters a call to one of the standard routines, it will
pull up and execute the implementation of that routine which
is appropriate for the particular platform on which it is running.
This is a very powerful idea. It means that you only need
to learn one API to program for a wide variety of platforms.
Like all subroutines in Java, the routines in the standard
API are grouped into classes. To provide larger-scale organization,
classes in Java can be grouped into packages.
You can have even higher levels of grouping, since packages
can also contain other packages. In fact, the entire
standard Java API is implemented in several packages. One of these,
which is named "java", contains the non-GUI packages
as well as the original AWT graphics user interface classes.
Another package, "javax", was added in Java version 1.2
and contains the classes used by the Swing graphical user interface.
A package can contain both classes and other packages. A package that
is contained in another package is sometimes called a "sub-package."
Both the java package and the javax package contain
sub-packages. One of the sub-packages of java, for example, is
called "awt". Since awt is contained
within java, its full name is actually java.awt.
This is the package that contains classes related to the AWT graphical
user interface, such as a Button class which
represents push-buttons on the screen
and the Graphics class which provides routines for
drawing on the screen. Since these classes are contained in
the package java.awt, their full names are actually
java.awt.Button and java.awt.Graphics.
(I hope that by now you've gotten the hang of how this naming thing works
in Java.) Similarly, javax contains a sub-package
named javax.swing, which includes such classes as
javax.swing.JButton and javax.swing.JApplet.
The java package includes several other sub-packages,
such as java.io, which provides facilities for input/output,
java.net, which deals with network communication,
and java.applet, which implements the basic functionality
of applets. The most basic package is called java.lang.
This package contains fundamental classes such as String
and Math.
It might be helpful to look at a graphical representation
of the levels of nesting in the java package,
its sub-packages, the classes in those sub-packages, and
the subroutines in those classes. This is not a complete picture,
since it shows only a few of the many items in each element:
Let's say that you want to use the class java.awt.Color
in a program that you are writing. One way to do this is to
use the full name of the class. For example, you could say
java.awt.Color rectColor;
to declare a variable named rectColor whose type
is java.awt.Color. Of course, this can get tiresome,
so Java makes it possible to avoid using the full names of
classes. If you put
import java.awt.Color;
at the beginning of a Java source code file, then, in the
rest of the file,
you can abbreviate the full name
java.awt.Color to just the name of the class, Color.
This would allow you to say just
Color rectColor;
to declare the variable rectColor. (The only
effect of the import statement is to allow you to
use simple class names instead of full "package.class"
names; you aren't really importing anything substantial. If you
leave out the import statement, you can still access the
class -- you just have to use its full name.) There is
a shortcut for importing all the classes from a given package. You
can import all the classes from java.awt by saying
import java.awt.*;
and you can import all the classes from javax.swing with the line
import javax.swing.*;
In fact, any Java program that uses a graphical user interface is likely to
begin with one or both of these lines. A program might
also include lines such as "import java.net.*;"
or "import java.io.*;" to get easy access to networking and
input/output classes. (When you start importing lots of packages in this way,
you have to be careful about one thing: It's possible for two classes that
are in different packages to have the same name. For example, both the
java.awt package and the java.util package contain classes
named List. If you import both java.awt.* and java.util.*,
the simple name List will be ambiguous. If you try to declare a variable
of type List, you will get a compiler error message about an ambiguous
class name. The solution is simple: use the full name of the class, either
java.awt.List or java.util.List. Another solution is to
is to use import to import the individual classes you need, instead of
importing entire packages.)
Because the package java.lang is so fundamental,
all the classes in java.lang are automatically
imported into every program. It's as if every program began with
the statement "import java.lang.*;". This is why we
have been able to use the class name String instead of
java.lang.String, and Math.sqrt() instead of
java.lang.Math.sqrt(). It would still, however, be
perfectly legal to use the longer forms of the names.
Programmers can create new packages. Suppose that you want
some classes that you are writing to be in a package named utilities.
Then the source code file that defines those classes must begin with the
line "package utilities;". Any program that uses
the classes should include the directive "import utilities.*;"
to obtain access to all the classes in the utilities package.
Unfortunately, things are a little more complicated than this.
Remember that if a program uses a class, then the class
must be "available" when the program is compiled and when it
is executed. Exactly what this means depends on which Java environment
you are using. Most commonly, classes in a package named utilities
should be in a directory with the name utilities, and that
directory should be located in the same place as the program that
uses the classes.
In projects that define large numbers of
classes, it makes sense to organize those classes into
one or more packages. It also makes sense for programmers
to create new packages as toolboxes that provide functionality
and API's for dealing with areas not covered in the standard
Java API. (And in fact such "toolmaking" programmers
often have more prestige than the applications programmers
who use their tools.)
However, I will not be creating any packages in this textbook. You need to know
about packages mainly so that you will be able to import the standard
packages. These packages are always available to the programs that
you write. You might wonder where the standard classes are actually located.
Again, that depends to some extent on the version of Java that you are
using. But they are likely to be collected together into a large file
named rt.jar or classes.zip, which is located in some place where the
Java compiler and the Java interpreter will know to look for it.
Although we won't be creating packages explicitly,
every class is actually part of a package.
If a class is not specifically placed
in a package, then it is put in something called the
default package, which has no
name. All the examples that you see in these notes are in
the default package.