Skip to main content.

Web Based Programming Tutorials

Homepage | Forum - Join the forum to discuss anything related to programming! | Programming Resources

Tricks of the Java Programming Gurus

Chapter 25 -- Class Organization and Documentation Tools

Chapter 25

Class Organization and Documentation Tools


CONTENTS




Sun Microsystems has some useful tools that aid in the organization and documentation of your Java classes. These tools enable you to logically group your classes and interfaces into packages, to generate documentation from properly commented source code, and to disassemble existing Java classes. These tools-the Java compiler javac, the Java documentation generation tool javadoc, and the Java disassembler javap-are included in the Java Developer's Kit (JDK). They are available on most supported platforms. This chapter describes how to use these tools to create packages of classes, to generate documentation from your Java source, and to disassemble compiled class files.

Java Packages

A Java package provides the means of organizing your classes and interfaces. Initially you can choose to develop your Java applet or application with all sources and classes residing in one directory. Because of the Java specification that every class be placed into a separate file, however, you can quickly become overwhelmed with class files. You can use packages to group together related classes and interfaces. In addition to the improved organization of classes, the packages also give member classes special access to other classes within the same package. This special default package access allows classes within the package to have public access to other members of the package. At the same time it excludes access by all classes external to the package. In this section, the steps involved in creating and using Java packages will be demonstrated.

To place a class in a user-defined Package, place a Package statement as the first non-comment, non-whitespace line in the source file:

package tools;
public class ToolA {
}

Note
All Java classes belong to a package. If there is no package statement in the source file for a class, the Java compiler places that class into a default unnamed package.

Compile class ToolA with the Java compiler command:

javac ToolA.java

The class ToolA now resides in the package tools. The result of the compile is the creation of a single class file ToolA.class.

Note
You may wonder why you see nothing different when you compile a class with a package statement than when you compile a class without a package statement. Nothing appears different because the knowledge that class ToolA belongs in package tools is stored within the class file.

All classes in a package are accessible by all other classes in the same package. A class is accessible to another class if it can be instantiated or extended by that class. Packaged classes can refer to classes from within the same package by their class name alone (not by their package name). For example, class ToolA, defined above, is visible to all other classes within the tools package. Any class within the tools package can instantiate or extend class ToolA without having to reference it by its package name. See the following example:

package tools;      // ToolB is also in the tools package
public class ToolB {
     ToolA t = new ToolA();     //  classes in same package can
                                //  be referenced by class name only
}

A class can belong to only one package at a time. For example, you can't have ClassA belonging to package tools and package util without duplicating the class and physically placing it in both packages. You don't want to have to maintain duplicate classes. So instead of this, you can simply import the class from its package into the class that needs it.

Importing Packaged Classes

If a class outside of a package requires a class from a package, the packaged class must be imported, that is, brought into the class. Placing a class in a package forces classes outside of the package to reference it differently than before because it essentially has a different name than before. Liken this to the area code changing on your telephone number: your neighbors can still call you by the same seven-digit number, but your long distance relatives won't be able to reach you until they use the correct area code. The package name is like the area code for the class. Local classes within the same package are still able to access each other as normal, but long distance classes from outside of the package must use the full packaged class name. Packaged classes are imported using an import statement.

Note
All import statements must be placed at the top of the source file after the package statement (if any) and before your class definitions.

The tools package example, shown previously, is used to illustrate the three ways in which packaged classes can be imported:

import tools.ToolA;      // import packaged class ToolA
public class ToolBox {
     ToolA t = new ToolA();     // ToolA class can now be referenced
                                // without its package name
}
import tools.*;         // import all classes within package tools
public class ToolBox2 {
     ToolA t = new ToolA();// ToolA class can now be referenced
                           // without its package name
}
public class ToolBox3 {
     tools.ToolA t = new tools.ToolA();     // direct import
}

Tip
It is a good idea not to import an entire package when you are using only one or two classes from that package. Importing all classes from a package increases the chances of namespace conflict, which means having more than one class by the same name. As you add new classes to the package over time, you increase the likelihood of having two or more classes with the same name if you import every class from a package. If you import only the classes that you need, duplication is less likely.

Note
Be prepared for compilation time to increase whenever you import one or more classes from a package.

Importing an entire package into a class does not increase the size of your class file because imported classes are not loaded at compile time; they are loaded when instantiated at run time. Also, using the asterisk wild card (*) to import all classes from a package does not import any subpackages of that package. For instance, the import statement

import java.awt.*
imports only the classes from the java.awt package. The subpackages java.awt.image and java.awt.peer are not imported. To import all classes from these packages, you must use two additional import statements:
import java.awt.image.*
import java.awt.peer.*

Tip
After you place your classes that are applets into a named package, you must change your HTML file to reference it by its packaged name. You must also set your CODEBASE to the directory located above the beginning of the package hierarchy (see the "CODEBASE Attribute" section later in this chapter for details on CODEBASE).
The following example of the packaged class, mypackage.DigClock, shows the applet tags within the HTML files before and after the class is placed in the package. "…" means the current working directory.
Before: DigClock.class (in directory .../home) is not in a user-defined package
<!-- HTML file : DigClock is not in a package-->
<APPLET CODE=DigClock.class CODEBASE="home/">
After: DigClock.class is in package mypackage in directory …/home/classes/mypackage
<!-- HTML file : ToolA is in the tools package-->
<APPLET CODE=mypackage.DigClock.class CODEBASE="home/classes">

Note
The package java.lang is a standard Java package and is automatically imported into every class for you by the compiler. Because of this you can access classes from this package (such as Integer and Object) without placing an import statement in your source code.

Now you have seen how to import a packaged class into a class outside of its package. The procedure seems straightforward, but this is where the problems can start. Often developers place their classes into packages with ease (just a package statement and a compile command places a class into a package), but when the developers attempt to import their classes into other classes, things become complicated. In fact, if you try to compile any of the previous examples of the class ToolBox, you may see the following error:

Type

javac ToolBox.java

Output

ToolBox.jav:1: Class tools.ToolA not found in import
import tools.ToolA;
^

Class ToolA is in the same directory as the ToolBox class, so why can't the compiler find it? The compiler can't find the packaged class ToolA because the compiler expects the class to reside in a directory with the same name as the package. This brings us to the relationship between package names and directory structure.

Package Names and Directory Structure

The directory structure in which packaged classes reside must match the name of the package. If it does not, the packaged classes are unusable until they are placed in a directory structure that does match its name. The class may be in your current directory, but the class loader will never recognize it. For example, the packaged class

tools.subtools.ToolA

must reside in the directory structure

…/tools/subtools/ToolA.class

If you attempt to access a packaged class that is not in a directory structure matching its name, the compiler generates an error similar to the following:

ToolBox.jav:1: Class subtools.ToolA not found in import
import subtools.ToolA;
^

Note
All classes belonging to a package must be in the same directory; they cannot be scattered in different directories. Even if two packages have the same name but their classes are in different directories, they are considered separate packages. The following shows the directory structure for two packages with the same name:
Package tools.subtools:
.../home/tools/subtools/*.class
Different Package tools.subtools:
.../usr/tool/subtools/*.class
Both packages have classes that belong to a package named tools.subtools, but the classes in these two directories are not accessible to each other because importing a package with the same name as the current package is considered by the compiler to be ambiguous.

Now is a good time to set up a directory structure for your packaged classes. Figure 25.1 depicts a standard directory structure for two Java packages. Notice that there are separate directories for your source, classes, and documentation. This reduces the confusion of having files with different suffixes all in one directory. Notice how the package name is mirrored beneath both the source and the classes directory structure.

Figure 25.1 : A sample Java development directory structure.

The package names, packageA and packageB, represent the fully qualified package name. Unlike a package with only one level to its name (such as packageA), some packages have more than one level to their names, such as pkg1.subpkg1.util. The directory structure would be as shown in Figure 25.2.

Figure 25.2 : Multi-level package name directory structure.

Note
Sun Microsystems has introduced a standard for making package names unique throughout the Internet. The standard calls for you to use the reverse of your domain name as the first part of the package name. For example, if my domain name were myCompanyName.COM, the first components in my package name would be COM.myCompanyName. The remaining components of your package name identify your unique organization and project within your company and the contents of the package, for example:
COM.myCompanyName.myOrg.myProject.myPackage
A unique packaged class name immediately associates ownership of a class to the company and division where it was written. This does make for a lengthy directory structure, however,
/java/classes/COM/myCompanyName/myOrg/myProject/myPackage/*.class
and need only be used if you are publishing a commercial class library on the Internet.

Once your packages of classes are created and are placed in separate directories, you must be able to inform the compiler and class loader where to find them in order for other classes to use them. This is done using the CLASSPATH environment variable.

CLASSPATH Environment Variable

CLASSPATH is an environment variable used by the compiler and the class loader to find Java class files. The CLASSPATH is set by the user and is simply a list of directories (separated by colons on UNIX platforms and semicolons on pc platforms) that will be searched to find Java classes.

If your CLASSPATH was not set before now, the compiler and class loader can see only the classes in your current directory. In order for you to do any Java programming, your CLASSPATH must be set to the directory containing Sun's Java Class Library of standard Java packages, as well as your current directory.

Note
If the JDK top-level directory is listed in your PATH environment variable, the Java compiler is automatically able to determine the location of the standard Java classes. You do not need to set the CLASSPATH. For the remainder of this chapter, it is assumed that the standard Java packages are known by the compiler without explicit modifications to the CLASSPATH.

Being able to use classes in only the current directory definitely limits reuse of classes. Naturally you want to be able to use another class (or package of classes) without having to copy it into your own directory. Setting the CLASSPATH to point to the directory where the desired class or package resides enables you to reference classes as if they were in your own directory.

The classes from the example tools package are in directory /home/tools/. Set the CLASSPATH in the following way so the compiler can find the classes in the tools package:

set CLASSPATH=C:\home                     // pc method of setting CLASSPATH
setenv CLASSPATH /home                    // UNIX method of setting CLASSPATH

Caution
Remember in the CLASSPATH to put the path name up to but not including your package name. If you do not specify the path name up to but not including your package name, your class will not be found because the compiler and class loader look for the directory matching the first word in your package name. Take, for example, the package named java.awt, whose classes are in directory /usr/classes/java/awt. The correct CLASSPATH to access this package is the following:
set CLASSPATH=.;C:\usr\classes // pc method of setting CLASSPATH
setenv CLASSPATH=.:/usr/classes // UNIX method of setting CLASSPATH

The dot (.) in the CLASSPATH stands for current directory. Usually you want the compiler to find the classes in your current directory as well as those in the package from which you are importing.

The order of the directories in the CLASSPATH is important. The directories are searched in left-to-right order. If the CLASSPATH is set as follows,

pc method of setting CLASSPATH:

set CLASSPATH=.;C:\usr\SUN;C:\home\java\classes

UNIX method of setting CLASSPATH:

setenv CLASSPATH=.:/usr/SUN:/home/java/classes

the current directory (.) is searched first, then /usr/SUN, and finally /home/java/classes. If a class with the same name is in each of these three directories, the class in the current directory is the one the compiler selects.

Instead of changing the CLASSPATH variable, you can specify a path in which to search for classes directly on the command line of the javac command by using the -classpath option. For example, the following command,

javac -classpath .:/usr/SUN:/home/java/classes *.java                   // UNIX
javac -classpath .;C:\usr\SUN;C:\home\java\classes *.java               // pc

compiles all Java files in the current directory and searches for any referenced classes first in the current directory, then in /usr/SUN, and finally in /home/java/classes. The path specified on the command line using the -classpath option overrides the path specified in the CLASSPATH environment variable.

In order for you to publish your applets on the Web, you must be able to reveal where your class files are.To inform the Class Loader where to search for your applet classes, you must use the CODEBASE attribute in the <APPLET> tag of your HTML file.

CODEBASE Attribute

Use an <APPLET> tag to reference the applet class when the applet is embedded within an HTML page. The <APPLET> tag provides the class name of the applet to be displayed on the HTML page within the browser. The Java Class Loader looks for the applet's classes only in the same directory as the HTML file itself unless you specify a different directory using the CODEBASE attribute.

The CODEBASE attribute of the <APPLET> tag is the name of one directory (not a list of directories as with CLASSPATH) in which to search for your applet class files. An example <APPLET> tag containing a CODEBASE follows:

<APPLET CODE="DigClock.class" CODEBASE="home">

You do not need to provide a full path name for the CODEBASE. Instead, you can give an offset from the directory where the HTML file resides. For example, if the HTML file is in directory .../temp/html and the applet class files are in .../temp/classes, set the CODEBASE as shown here:

<APPLET CODE="DigClock.class" CODEBASE="../classes">

Note
The CODEBASE can also be assigned a URL:
<APPLET CODE="DigClock.class"
CODEBASE="http://a.b.com/digclock">
This is especially useful if you want to reference another person's applet from your HTML page, but you do not want to or you cannot copy their applet class files.

Only one directory can be specified in the CODEBASE. Because of this, all associated class files for your applet must be in one directory in order for the applet to be embedded in an HTML page.

Tip
On UNIX platforms you can circumvent the limitation of having to place all class files for your applet into one directory. To do this, place the classes you want to access in packages and provide filesystem links from the CODEBASE directory to the package path.

The directory specified in the CODEBASE for packaged classes must follow the same convention as does CLASSPATH. The path name up to but not including the package name must be given. If the packaged applet class tools.AppletTool residing in directory .../home/tools/ were to be embedded in an HTML file, the <APPLET> tag would look as follows:

<APPLET CODE="tools.AppletTool.class" CODEBASE="home">

The CODEBASE attribute in an HTML file and the CLASSPATH environment variable provide a path to be searched for classes. Once a class is found on the path, it is evaluated for accessibility to see if it can be subclassed or instantiated. Class accessibility is set by the programmer of a class with access modifiers. The relationship between access modifiers and packaged classes is discussed in the following section.

Class Accesses and Packages

Java enables programmers to hide certain aspects of the implementation of their classes from other classes. This is in keeping with the object-oriented philosophy that objects should reveal only the minimum amount of information required to use that object and no more. Hiding in Java is done using access modifiers to control which classes have access to other classes and their variables and methods. When a class is placed in a package, special access privileges are granted to the members of that package. This section explains class accessibility and its relationship to packages.

There are four access modifiers-public, protected, private protected, and private. When you place one of these four access modifiers before the declaration of a class, variable, or method, you define which other classes are able to access the declared item. Accessibility ranges from all other classes having access to no other classes having access. If none of the access modifiers are used in a declaration, the access defaults to a package, known as friendly access.

To have access to a class means to have the ability to subclass or instantiate that class. There are only two different types of access for a class:

To have access to a variable means to have the ability to change or examine the value of the variable. To have access to a method means to have the ability to execute or override that method. There are five different types of access for a variable or method:

The default package access gives the programmer freedom within a package to access other classes of that package without having to deal with access restrictions. At the same time, the default package access of a packaged class excludes access by any class outside of the package, promoting implementation hiding.

If you get compilation errors when you attempt to group your classes into separate packages, verify that your CLASSPATH is properly set and your classes are in the correct directory structure for their package name. If they are, then the access type of a class, variable, or method is the probable cause of the problem.

Many programmers unintentionally leave off access modifiers, and this means that their constructors, methods, variables, and classes have the default package type access. This would go unnoticed if all classes were in one package together or were not in a user-defined package. But once the programmer attempts to divide classes into different packages, then classes no longer have access to methods and variables that they did before.

An example of cross-package errors is illustrated in the following two listings, with two classes in separate packages: tools.ToolC and util.ClassA.


Listing 25. 1. Importing ClassA from package util.
package tools;
import util.*;

public class ToolC {
     ClassA a = new ClassA(this);   //  attempting to instantiate
                                    //  class from another package
}


Listing 25. 2. Importing class ToolC from package tools.
package util;
import tools.*;

public class ClassA {
     ClassA (ToolC tc) {}          //  constructor has default package access
}

The error that follows is the result of compiling the above two classes. Both classes have the correct import statements to import each other. But class tools.ToolC attempts to access a constructor from class util.ClassA and the constructor for util.ClassA has the default package access, which makes it inaccessible to classes outside of its package.

./tools/ToolC.java:6: No constructor matching
ClassA(tools.ToolC) found in class util.ClassA
ClassA a = new ClassA(this);
1 error    ^

If the access modifier public is placed before the constructor for class util.ClassA, it compiles without errors.

The accessibility type of a variable or method determines whether or not it will be visible in the API documentation generated by the Sun tool javadoc. The API document generation tool is described in the following section.

Documentation Generation Using javadoc

Documenting applets and applications is not a favorite task for most programmers, but the Sun JDK includes an API documentation generation tool, named javadoc, which makes it less painful. javadoc generates documentation from your properly commented Java source. With this tool you can produce polished HTML file documentation similar to the Sun Java API. Because the documentation is generated from the source, there is no longer a problem with outdated documentation. The documentation always reflects the current state of the source. Also, because the documentation is in HTML format, users can breeze from one associated class to another with a press of the mouse button on a hyperlink.

The javadoc tool is capable of generating HTML files containing the following:

The class NotDocumentedClass looks as follows:

import java.awt.*;
public class NotDocumentedClass extends Panel {
public NotDocumentedClass ()  {
       super();
       Color currentcolor = getBackground();
    }
public void addButton(String label){
       if (label == null) label = "EmptyButton";
       add(new Button (label));
    }
}

Note
javadoc generates documentation only for variables and methods with public, protected, or private protected access. Any comments relating to private or default package variables and methods are not translated to the output documentation. This is in keeping with object-oriented methodology where only what is accessible to others should be revealed.

To generate documentation for the NotDocumentedClass class (which is in the default unnamed package), execute the javadoc command with the class source file name as an argument. Remember, the documentation is generated off of the source file, so you must inform javadoc where your source is. You can do this in one of three ways: you can change into the same directory as the source file, you can fully qualify the directory name of the source file, or you can use the -classpath option of the javadoc command.

Note
The -classpath option enables you to specify a list of directories where the search for your Java source files is to occur. Take, for example, the class named NotDocumentedClass, whose source is in directory .../source/. The correct usage of the -classpath option in the javadoc command to access this source would be:
javadoc -classpath /usr/source NotDocumentedClass.java       // UNIX
javadoc -classpath C:\usr\source NotDocumentedClass.java     // pc

As discussed in the "Package Names and Directory Structure" section, it is a good idea to place your documentation in a separate directory. This keeps it separate from your source and classes and allows for hyperlinks to associated classes and interfaces. Currently all documentation must be in a single directory in order for related classes to link to each other. The -d option of the javadoc command enables you to specify in which directory your output is to be placed. To generate documentation for the class NotDocumentedClass, type the following:

mkdir doc
javadoc -d doc NotDocumentedClass.java

You should get the following output:

Loading source files for NotDocumentedClass
Generating packages.html
Generating index
Generating tree

Table 25.1 lists all of the HTML files generated by javadoc for a class (ex. NotDocumentedClass) and placed in the doc directory.

Table 25.1. Generated documentation files for NotDocumentedClass.

FilenameDescription
AllNames.htmlHyperlinked alphabetized list of all fields and methods
NotDocumentedClass.htmlClass hierarchy and description for NotDocumentedClass
packages.htmlHyperlinked list of all packages (empty, NotDocumentedClass is in default unnamed package)
Package-NotDocumentedClass.htmlPackage description and hyperlinked contents (empty)
tree.htmlHyperlinked list of all classes

Note
SUN's JDK contains an apidocs directory (for example,.../Java/apidocs/), which contains the HTML files and a subdirectory of gif images that make up the Java API documentation. These directories contain the HTML documentation for all Java standard classes as well as all associated gif images (such as color coded bullets). To make your documentation appear as polished as the Java API and to permit links to Java standard classes from your HTML documentation, you can do one of two things: copy the contents of the apidocs directory to your local documentation directory, or place your documentation HTML files in the JDK apidocs directory.

Use your Web browser to view the HTML files generated by javadoc. At this point, the HTML files for the class NotDocumentedClass do not contain much information about the class. To produce more substantial documentation, you have to comment the source according to the javadoc specifications. The following sections demonstrate how to properly comment your source and relate which javadoc options to use in generating HTML documentation. Generating documentation for one or more packages is also described.

Comments and Documentation Tags

Within your Java source, any text between the comment delimiters /** and */ can be placed into the output API documentation by javadoc. With this capability you can document the source of your classes, interfaces, variables, and methods in great detail. Your effort will not be wasted because javadoc will transfer it into the output documentation. The comments you provide must immediately precede the class, variable, or method which they describe. Any comments placed incorrectly are silently ignored by javadoc. For example, see the placement of comments for class DocumentedClass:

import java.awt.*;
/**
  * Class comment: DocumentedClass is a container for buttons
  */
public class DocumentedClass extends Panel {

/**
  * Variable comment: numbuttons is a counter of buttons
  */
       public int numbuttons = 0;

/**
  * Constructor comment: Constructs the DocumentedClass.
  */
    public DocumentedClass () {
/** This comment will not be placed in the API documentation */
       super();
       Color currentcolor = getBackground();
}

/**
  * Method comment: Add a button with specified label.
  */
    public void addButton(String label){
       if (label == null) label = "EmptyButton";
       add(new Button (label));
       ++numbuttons;
    }
}

Executing javadoc on the preceding file

javadoc -d doc DocumentedClass.java

results in the generation of HTML files, in which comments are placed with their associated class, variable, or method. Notice the comment within the constructor does not precede any class, variable, or method, so it is ignored by javadoc.

Within the comment delimiters, you can also use documentation tags (keywords that begin with @), which are treated specially by javadoc. Table 25.2 lists the documentation tags recognized by javadoc and the resulting output of these tags.

Table 25.2. Javadoc documentation tags.

Documentation TagParameters Description
Class Tags
@author 1 author_name Adds field for author of class (must use -author option of javadoc command).
@see 1 class_name or method_name Adds hyperlinked field labeled See Also to specified class or method.
@version version_name_number Adds field for version of class (must use --version option of javadoc command).
Method Tags
@exception class_name description Adds hyperlinked field labeled Throws with name of exception thrown by method.
@param 1 parameter_name description Adds field for method parameter.
@return return_name description Adds field for value returned by method.
@see 1 class_name or method_name Adds hyperlinked field labeled See Also to specified class or method.
Variable Tags
@see 1 class_name or method_name Adds hyperlinked field labeled See Also to specified class or method.

Note
You can specify more than one of these tags on separate lines between one set of comment delimiters. For instance, use multiple @author tags for a list of authors separated by commas to be shown in the output documentation. Keep same name tags together in your source or they will be ignored.

The tags that are used within comment delimiters for a class are different from the tags used within comment delimiters for a method or variable. In fact, if you attempt to place a documentation tag that is meant only for the class comments such as @author in the method comment section of the source, javadoc will silently ignore it.

Caution
After a comment asterisk and before the documentation tag, there can be up to one space. If you place any more spaces between the comment asterisk and the documentation tag, the tag is either silently ignored or appended to the previous tag.

/**
 * @author Ben Taylor            // Valid
 *@author Ben Taylor             // Valid
 *        @author Ben Taylor     // 2Invalid
 **/

Tip
You may go to a lot of trouble placing the @author and @version documentation tags in your source with the correct number of spaces, but you won't be able to see the tags in your output documentation unless you specify the related option on the command line, for example
javadoc -author -version *.java

A list of all javadoc command line options is given in Table 25.3. Some of these options are not documented in the Java Language Specification, but if you do not use them on the command line, your output API will not be what you expected.

Table 25.3. Javadoc command line options.

Command Line OptionDescription
-author Process any @author tags within source files
-authors Same results as -author option
-classpath path List of directories (separated by ':') containing java source
-d directory Output directory for API documentation
-depend package1 package2 ... Allow dependencies of API documentation between packages
-version Process any @version tags within source files
-verbose Print messages to screen about source being processed

Thus far you have placed standard comments and documentation tags in your comment delimiters. javadoc also enables you to embed HTML tags within your comments. The following section describes this in detail.

Embedded HTML

javadoc enables you to embed HTML tags within your comment delimiters. This is a powerful feature of javadoc and opens up your documentation to nearly all of the special publishing capabilities of HTML. Your API documentation is in an HTML file and can be configured by you. You can add hyperlinks to other HTML files, load images, color text, and do almost anything else you can do with a regular HTML file. HTML is especially useful within your API documentation to provide hyperlinks to related classes or source listing, or to provide examples of how to use your class. Listing 25.3 demonstrates the many uses of HTML within a Java class:


Listing 25.3 Example of embedded HTML within Java commented source.
import java.awt.*;
import java.applet.*;
import java.util.Vector;

//      CLASS:  EmbeddedHTMLClass
/**
 *      This applet displays the text specified in the <i>title</i>
 *      parameter. The initial background color of the applet is
 *      specified in the <i> bgcolor </i> parameter.
 *<p>
 * Following is an example APPLET tag for the EmbeddedHTMLClass class.
 * <pre>
 *       Usage:
 * < APPLET CODE="EmbeddedHTMLClass.class" WIDTH=100 HEIGHT=100>
 * < PARAM NAME=bgcolor VALUE="red" >
 * < PARAM NAME=title   VALUE="Test Title" >
 * < /APPLET >
 * </pre>
 * <p><b>Sample background colors for the <i> bgcolor </i> parameter follow:</b>
 * <p><li>"red"
 * <li>"blue"
 * <li>"green"
 * <li>"yellow"
 *
 * @see Color
 * @see Button
 * @version 1.0 27 June 1996
 * @author <A HREF="http://mydomain.name.com/Home.html">Greg Mitchel</A>
 */
public class   EmbeddedHTMLClass extends Applet {
//      EmbeddedHTMLClass Class Data

/** Title to Display */
        protected String          title = null;

/** Background color  */
        protected Color           bgcolor;

/** Changing colors  */
        private int red   = 0;
        private int blue  = 50;
        private int green = 50;
        private Color currentcolor = null;

//      constructor: EmbeddedHTMLClass
   /**
     *  Constructs the EmbeddedHTMLClass.
     */
    public EmbeddedHTMLClass ()  {
         super();
         bgcolor = getBackground();
}


/**
  * Initialize EmbeddedHTMLClass Applet.
  */
    public void init(){

        setLayout(new BorderLayout());

        String param = getParameter( "BGCOLOR"  );
        if ( param != null ) {
            if (param.equals("red"))         bgcolor = Color.red;
            else if (param.equals("blue"))   bgcolor = Color.blue;
            else if (param.equals("green"))  bgcolor = Color.green;
            else if (param.equals("yellow")) bgcolor = Color.yellow;
            else bgcolor = Color.blue;
        }
        else bgcolor = Color.blue;

        setBackground(bgcolor);

        title = getParameter( "TITLE"  );
        if ( title == null )
            title = "Default Title";

        Button b = new Button("Change Color");
        add("South", b);

    }

/**
  * Change color of background at button press.
  * @param event The action event to be handled.
  * @param obj Target object of the event to be handled.
  * @return Handled event flag.
  */
    public boolean action(Event event, Object obj) {

       if (event.target instanceof Button) {

            red   += 20;
            blue  += 20;
            green += 20;
            if (red   > 255) red   = 0;
            if (blue  > 255) blue  = 0;
            if (green > 255) green = 0;
            currentcolor = new Color(red, green, blue);
            setBackground(currentcolor);
            update(getGraphics());
            return true;

       }

       return false;

    }


 /**
  * paint()
  * Set background color, display title.
  * @param g The graphics context on which to paint.
  */
   public void paint(Graphics g) {
         if (currentcolor != null)
             setBackground(currentcolor);
         g.drawString(title, 10, 30);
    }
}

Figure 25.3 illustrates a portion of the output API documentation with embedded HTML generated by the javadoc command

Figure 25.3 : Sample Java API with embedded HTML.

javadoc -d doc -version -author EmbeddedHTMLClass.java

for class EmbeddedHTMLClass.

Note
javadoc specifications warn users not to embed the following HTML heading tags in their API documentation because they interfere with document formatting:
The horizontal line tag: <HR>
The six heading level tags: <H1>-<H6>
However, javadoc does not generate any errors when these tags are encountered.

Documentation Generation and Packages

You have learned how to generate API documentation for your unpackaged classes. This section demonstrates how to generate documentation for one or more packages of classes. Like unpackaged class documentation, javadoc can produce class hierarchy diagrams, and it can do so for each class in a package. In addition to this, it can generate a hyperlinked listing of all of your packages and lists of classes within these packages. This hyperlinked representation of your packages and classes is a valuable reference resource for users of your classes. It facilitates reuse of classes by providing clear definitions of accessible variables and methods within the class and in any superclasses.

In this example, API documentation is generated for the package acct.util which contains four classes: ClassA, ClassB, ClassC and ClassD. To do this, you must execute the javadoc command with the fully packaged class name as an argument. Once again, the documentation is generated off of the class source files, so change into the directory just above the first directory in the package name (for example, the directory above acct), or use the -classpath option of the javadoc command.

Caution
The -classpath option of the javadoc command enables you to specify a list of directories in which the search for your Java source files is to occur. When you generate documentation for a package, you must give the path name up to, but not including, the first directory of the package name. If you do not, your source file can not be found because javadoc looks for the directory matching the first word in your package name. Take for example the package named acct.util, whose source files are in directory .../usr/source/acct/util. The correct classpath to access this package would be
javadoc -classpath /usr/source acct.util

The -d option of the javadoc command enables you to specify the directory name in which the output documentation is to be placed. The source files for the acct.util package are in directory .../usr/source/acct/util. To generate documentation for the entire acct.util package, type the following:

cd source
javadoc -d doc acct.util

You should get this output:

Loading source files for acct.util
Generating packages.html
generating documentation for class acct.util.ClassA
generating documentation for class acct.util.ClassB
generating documentation for class acct.util.ClassC
generating documentation for class acct.util.ClassD
Generating index
Sorting 4 items . . . done
Generating tree

Often there are class dependencies between packages. A class from one package will instantiate or extend a class from another package. You want your documentation to show these dependencies through hyperlinks (example: have the ability to jump from extended class definition to superclass definition). This can be done using the javadoc tool with its -depend option.

In the next example, API documentation is generated for the three packages: pkgA.util, pkgB.tool, and, pkgC.awt. Again, the documentation is generated off of the class source files. Change into the directory just above the first directory in the package name (for example, the directory above pkgA) or use the -classpath option of the javadoc command. The source files and the directory in which they reside are shown in Table 25.4.

Table 25.4. Packages pkgA.util, pkgB.tool, and pkgC.awt and associated directories.

Package NameDirectory
pkgA.util .../usr/source/pkgA/util
pkgB.tool .../usr/source/pkgB/tool
pkgC.awt .../usr/source/pkgC/awt

To generate interdependent documentation for the three packages at once, type the following:

javadoc -d doc -classpath /usr/source -depend pkgA.util pkgB.tool pkgC.awt

This is the output:

Loading source files for pkgA.util
Loading source files for pkgB.tool
Loading source files for pkgC.awt
Generating packages.html
generating documentation for class pkgA.util.ClassA
generating documentation for class pkgA.util.ClassB
generating documentation for class pkgA.util.ClassC
generating documentation for class pkgB.tool.ClassA
generating documentation for class pkgB.tool.ClassB
generating documentation for class pkgB.tool.ClassC
generating documentation for class pkgC.awt.ClassA
generating documentation for class pkgC.awt.ClassB
generating documentation for class pkgC.awt.ClassC
Generating index
Sorting 9 items . . . done
Generating tree

This provides a hyperlinked index of all three packages (packages.html), a hyperlinked index of classes for each package, class hierarchy diagrams, and a merged alphabetical index of all methods and variables (AllNames.html).

Class Dissassembly Using javap

Another useful tool that is included in the Sun JDK is a class disassembler tool named javap which disassembles class files. This tool can be used to determine whether your path environment variables are correctly set. Try and disassemble a standard Java class like java.awt.Button.class. Type the following:

javap java.awt.Button

Here is the output:

Compiled from Button.java
public class java.awt.Button extends java.awt.Component {
    java.lang.String label;
    public java.awt.Button();
    public java.awt.Button(java.lang.String);
    public synchronized void addNotify();
    public java.lang.String getLabel();
    public void setLabel(java.lang.String);
    protected java.lang.String paramString();
}

If, instead of printing the output above, javap prints an error message that says the class java.awt.Button cannot be found, your PATH or CLASSPATH environment variables are incorrectly set. See the section "CLASSPATH Environment Variable" for details.

To disassemble a nonstandard class such as MyClass.class, which is not in a user-defined package, you must fully qualify the class name (without the .class suffix), or change into the directory in which the class file resides (example: .../Java/classes) and type the following:

javap MyClass

Here is the output:

Compiled from MyClass.java
public class MyClass extends java.lang.Object {
     int x;
      public MyClass();
}

To disassemble the packaged class tools.ToolA.class, which resides in directory .../Java/classes/tools, change into that directory and type the following:

javap tools.ToolA

The disassembled class will be printed to the command line. This tool is useful if you do not have access to the source of a class, or if you do have API documentation but want to see the private variables or methods of a class. Table 25.5 lists the command line options of interest to the Java class disassembler.

Table 25.5. Javap command line options.

Command Line OptionDescription
-c Disassembles the code of the Java class (not private fields and methods)
-classpath The path of directories in which to search for classes (for example, .:Java/classes:new/classes)
-h Creates information that can be put into a C header file
-l Provides line numbers in output
-p Disassembles private variables and methods
-v Verifies options, prints out debugging information
-version Prints out the version number of javap (for example, "version 1.0.1")

Summary

In this chapter, several useful tools that are a part of the Sun JDK were discussed. The Java compiler javac was used to show how to create packages of Java classes and how to import packaged classes into other classes. There are two major benefits to placing Java classes into user-defined packages. First, class organization is greatly improved because classes are logically grouped together. Second, members of packages can take advantage of package class access privileges that are not available to classes outside of a package. The environment variable CLASSPATH and the HTML Applet tag CODEBASE were introduced. Usage of the API documentation generation tool javadoc was demonstrated. This tool generates professional looking API documentation from properly commented Java source code. And finally, the Java class disassembler tool javap was discussed.