A package is a group of related classes and interfaces. A big part of what we call Java is actually the extensive set of packages that accompany the syntax and language primitives. Java programmers can extend the language in this same way, by defining useful groups of classes and interfaces and providing them as packages.
There are several good reasons to create packages. Some are about communication. Grouping classes and interfaces together in a package is a way to tell other programmers that they are related. It also helps programmers find the classes and interfaces related to what they want to do.
Some of the reasons are about writing programs. A package creates a separate namespace. It allows us to have and use classes that have the same name, by having the classes reside in different packages. In Java, members of a package can be given access to one another that is not available to other classes. This means that a package creator can grant unrestricted access to one set of classes while providing limited access to classes outside the package. (To me, this often feels like friend status in a C++ program.)
The names of Java's built-in packages are all of the form java.package, such as java.io and java.util. Java also nests some packages inside other others, such as java.awt and java.awt.event.
User-created packages can have single-word names. In the case of our strategies for testing words in documents, we might name our package wordfeature.
A common convention for naming multiple packages from the same source or installation is to use the domain name of the creator. For instance, I might make a package named edu.uni.cs.wallingf to contain all of the code I use, or edu.uni.cs.wallingf.cs2530 for all the code we use in Intermediate Computing. Package names qualified in this name indicate that the packages are nested as subdirectories, like Java's.
Let's demonstrate the process of creating and using packages by packaging up all the files for our word feature strategies in a package named wordfeature.
This includes the WordFeature interface, the concrete strategies StartsWith, OfLength, and IsAPalindrome, and the composite CompoundFeature.
This must be top non-comment line of the file. For example, WordFeature.java becomes
package wordfeature;
public interface WordFeature
{
public boolean hasFeature( String s );
}
That's all there is to creating the package. Now let's use it.
The simplest way to use a package of this sort is to place its directory in the same directory with the code that uses it. Suppose that my working directory contains our wordfeature package:
> ls -al
...
-rw-r--r-- 1 wallingf staff 1710 Dec 7 14:32 Play.java
-rw-r--r-- 1 wallingf staff 811 Dec 7 14:28 WordLengths.java
-rw-r--r-- 1 wallingf staff 191734 Dec 7 14:30 hamlet.txt
drwxr-xr-x 8 wallingf staff 272 Dec 7 14:37 wordfeature
There are two ways to refer to members of the package in our programs. One way is to import all the members. For example, I added a new import directive at the top of WordLengths.java:
import java.io.IOException;
import wordfeature.*;
This is a common way to import a large number of classes and
interfaces at once, say, from the java.awt packages.
Another way is to import individual members. For example, I added several new import directives at the top of Play.java:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Vector;
import wordfeature.WordFeature;
import wordfeature.StartsWith;
import wordfeature.OfLength;
I like to import members individually whenever I would like
readers (including me!) to be able tell which classes and
interfaces are being used in the class. I often do this in
Intermediate Computing.
Finally, you may refer to a package member without importing it if you use its full-qualified name. For example, in Play.java, I used the IsAPalindrome class without importing it:
public int numberOfPalindromes()
{
return countWords( new wordfeature.IsAPalindrome() );
}
I don't know how often this is done in industry, or when. I
rarely do this.
Now we compile Play.java and WordLengths.java and run them as usual:
> javac WordLengths.java
> java WordLengths hamlet.txt 10 p
The document in the file hamlet.txt contains ...
0 words of 1 characters
1 words of 2 characters
123 words of 3 characters
206 words of 4 characters
118 words of 5 characters
131 words of 6 characters
169 words of 7 characters
128 words of 8 characters
40 words of 9 characters
31 words of 10 characters
... that start with 'p'.
Dandy!
If you want to use a package in many programs from multiple directories, you won't want to copy the directory into all those locations. Instead, put it into a common location with your other packages and make sure the path to the package is on your Java classpath.