This tutorial covers:
The Java Development Kit (JDK) includes a tool called Javadoc which generates documentation for Java source code with comments written in accordance with the Java documentation style. Take a quick look at the following links to see more examples.
Copy this tutorial directory (~comp212/public_html/01-spring/labs/02/) into your own directory. It includes Java source code for a version of lists. Use Emacs to look at both the code and the comments, which follow the Javadoc conventions.
Run the Javadoc utility on this code using
javadoc *.javaBrowse the generated HTML files using Netscape's File menu option Open Page. Does the documentation include descriptions of the private fields and methods?
Now execute the command:
javadoc -private *.javaWhat's the difference?
Now try simply
javadocLike many UNIX commands, running the program without specifying anyoptions will provide a brief description of its possible usage. Take a brief look at the explanation of the flags. In particular, note the
-d
flag for putting the
documentation into a separate directory.
A Java package is a grouping of classes similar to the notion of a
directory is a grouping of files. Packages are used to help avoid
name clashes and to hide particular pieces of code from the clients.
A package has a name, such as utility
or
java.lang.util
.
In general, a package name is a series of strings of alphanumeric
characters (starting with an alphabetic character)
and separated by periods. To make a java class part of a particular
package, say list
, you must
add the declaration package list;
to the very top
of the class source file.
Also, you will need to put the file in the directory structure that
mirrors the package name. For example, the java classes that belong
to the package list
should be in a directory also named
list
.
If you don't do this, it will still compile, but it won't run correctly.
Add the package list;
declaration to the top of
AList.java
.
You need to create a subdirectory called list
and
move AList.java
into it.
Now compile using
javac list/AList.javaNote that you should always compile from your project's main directory. If you compile from within a package subdirectory, it doesn't find all the supporting definitions.
We can't run anything yet, because that's just a piece of the whole program.
Add the package list;
declaration to the top of
EmptyList.java
and NEList.java
,
and move them into the list
subdirectory.
Do not make ListClient.java
part of
the package.
ListClient.java
does not have a package name, and it
thus said to be in the no-name (or default)
package.
Also, remove the public
access from the
EmptyList
and NEList
classes.
By default, a class is "package-private", i.e., it is known
within the package, but not from outside.
If you try to compile ListClient.java
now, you will get an error message. Try it to see what happens.
You need to add the statement import list.*;
to the
top of ListClient.java
to indicate to the compiler
that you are using all the public
classes in that package.
Try to compile it again.
You should see a few error messages saying that you can't use
EmptyList.java
and NEList.java
because these classes are not public.
This is because the ListClient
class is not part of
the list
package.
One way to resolve this problem by making ListClient
part of
the list
package. A class of a package can access
all the classes (public or "package-private") in the package.
However this is not a good solution in general because a client
may be using many classes from different packages, but not class
can be part of more than one package.
A better solution is to use a "factory".
Good software engineering practices advocate the principle of
"information hiding": all implementation details should be hidden
from client code. In the case of our lists,
EmptyList.java
and NEList.java
are the
details that clients should not know about.
The client should only program to the AList
abstraction. For this reason EmptyList.java
and
NEList.java
are not public classes. But the client needs
to have a way to create concrete instances of EmptyList
and NEList
somehow.
A solution is to add a public "factory"
class that is part of the list
package, which knows
how to call the list constructors to manufacture these classes.
Such a class follows the "factory design pattern".
Put the following in a file called
ListFactory.java
:
package list; /** * Manufactures AList objects. * Implemented as a singleton. * * @author Dung X. Nguyen * @version 1.0 * @since 09/10/00 * @Custom Copyright 2000 -All rights reserved */ public class ListFactory { public final static ListFactory Singleton = new ListFactory (); private ListFactory() { } public AList makeEmptyList() { return EmptyList.Singleton; } /** * Creates a non-empty list with a given non-null first element * and a non-null tail. * Throws an IllegalArgumentException if any of the parameters is null. * * @param first != null, the first element of the non-empty list. * @param rest != null, the rest of this non-empty list. */ public AList makeNEList(Object first, AList rest) { if (first == null || rest == null) { throw new IllegalArgumentException ("first and rest must be non-null."); } return new NEList (first, rest); } }
To use the factory, we must change our uses of lists.
Change ListClient
's main
method to
/** * A few simple test cases. */ public static void main (String[] args) { AList pc0 = ListFactory.Singleton.makeEmptyList (); AList pc1 = ListFactory.Singleton.makeNEList (new Integer (-1), pc0); AList p1 = ListFactory.Singleton.makeNEList ("-5", pc0); // NOTE: "-5" is a String, not an Integer! AList p2 = ListFactory.Singleton.makeNEList (new Integer (2), p1); AList p3 = ListFactory.Singleton.makeNEList (new Integer (-4), p2); AList p4 = ListFactory.Singleton.makeNEList (new Integer (3), pc1); System.out.println ("Empty List = " + pc0); System.out.println ("(-1) = " + pc1); System.out.println ("(3 -1) = " + p4); System.out.println ("(-5) = " + p1); System.out.println ("(2 -5) = " + p2); System.out.println ("(-4 2 -5) = " + p3); }
Note that the factory checks for valid NEList
constructor parameters, so remove that check from the original code.
Compile the code and run it.