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.