Chapter 19. Documentation Comments

 

Any member introducing a dog into the Society's premises shall be liable to a fine of £10. Any animal leading a blind person shall be deemed to be a cat.

 
 --Rule 46, Oxford Union Society (circa 1997)

Documentation comments, usually called doc comments, let you associate reference documentation for programmers directly with your code. The contents of the doc comment can be used to generate reference documentation, typically presented using HTML.

Doc comments are generally designed as fairly terse reference documentation. The reference documentation typically covers the contract of the documented interface, class, constructor, method, or field to the level of detail most programmers need. This approach is distinct from a full specification, which can be too long for reference documentation. A full specification might devote several pages of text to a single method, whereas reference documentation might be one or two paragraphs, possibly even short ones. Specifications should be produced separately, although they can be cross-referenced by the doc comment, as you will soon see.[1]

The procedure for generating documentation from the doc comments varies among development environments. One common procedure is to run the javadoc command on the packages or types; hence, the generated documentation is often called javadoc.

This chapter teaches what can go into documentation comments and how the contents are interpreted. You will also learn about features that are, strictly speaking, outside the language but are conventions for creating the generated documentation, such as overall package documentation and the location for images and other resources. Your development environment may not use these details in precisely the same way as javadoc but it is likely to, and if not will usually have an analogous replacement. These features are covered in the section “External Conventions” on page 496.

The Anatomy of a Doc Comment

Doc comments start with the three characters /** and continue until the next */. Each doc comment describes the identifier whose declaration immediately follows. Leading * characters are ignored on doc comment lines, as are whitespace characters preceding a leading *. The first sentence of the comment is the summary for the identifier; “sentence” means all text up to the first period with following whitespace. Consider the doc comment:

/**
 * Do what the invoker intends.  "Intention" is defined by
 * an analysis of past behavior as described in ISO 4074-6.
 */
public void dwim() throws IntentUnknownException;

The summary for the method dwim will be “Do what the invoker intends.” Your first sentence in a doc comment should be a good summary.

HTML tags are often embedded in doc comments as formatting directives or cross-reference links to other documentation. You can use almost any standard HTML tag. Be careful when using the header tags <h1>, <h2>, and so on, because they can disrupt the structure of the overall documentation—however, they are usually safe to use within class and package documentation. To insert the character <, >, or & you should use &lt;, &gt;, or &amp;, respectively. If you must have an @ at the beginning of a line, use &#064;—otherwise, an @ is assumed to start a doc comment tag.

Only doc comments that immediately precede a class, interface, method, or field are processed. If anything besides whitespace, comments, or annotations are between a doc comment and what it describes, the doc comment will be ignored. For example, if you put a doc comment at the top of a file with a package or import statement between the doc comment and the class, the doc comment will not be used. Doc comments apply to all fields declared in a single statement, so declaring multiple fields in a single statement is usually avoided where doc comments are used.

Tags

Doc comments can contain tags that hold particular kinds of information. Tags come in two forms:

  • Block tags define stand-alone text elements. All these tags start with @, as in @see or @deprecated. These paragraphs are treated specially in the generated documentation, resulting in marked paragraphs, links to other documentation, and other special treatment. This section describes all tags except @serial, @serialData, and @serialField, which relate to object serialization and are described in “The Object Byte Streams” on page 549.

  • In-line tags can occur anywhere within the text of a documentation comment and are used to apply special formatting, such as {@code} for use of code font, or to produce special text, such as creating a hypertext link using {@link}. In-line tags all have the form {@tag-name args} where the optional args value might provide text to be formatted or the target of the link, for example.

Except for tagged paragraphs and in-line tags, text in a doc comment is treated as input text for HTML. You can create paragraph breaks in the documentation with the standard <p> tag, blocks of example code using <pre>, and so on.

Not all tags need be processed by the javadoc tool by default; consult your tool documentation for details on what is needed to process which tags.

@see

The @see tag creates a cross-reference link to other javadoc documentation. You can name any identifier, although you must qualify it sufficiently. You can, for example, usually name a member of a class with its simple name. However, if the member is an overloaded method, you must specify which overload of the method you mean by listing the types of parameters. You can specify an interface or class that is in the current package by its unqualified name, but you must specify types from other packages with fully qualified names. You specify members of types by a # before the member name. The following are all potentially valid @see tags:

@see #getName
@see Attr
@see com.magic.attr.Attr
@see com.magic.attr.Deck#DECK_SIZE
@see com.magic.attr.Attr#getName
@see com.magic.attr.Attr#Attr(String)
@see com.magic.attr.Attr#Attr(String, Object)
@see com.magic.attr
@see <a href="spec.html#attr">Attribute Specification</a>
@see "The Java Developer's Almanac"

The first form refers to the method getName in the same class or interface as the doc comment itself, or in any enclosing class or interface; the same syntax can be used for constructors and fields. The second form refers to a class in the current package or an imported package. The third refers to a class by its fully qualified name.

The next four @see forms refer to members. The first two show forms for a field (DECK_SIZE) or method (getName). We can simply use the name of a method because exactly one getName method is defined in the Attr class. The next two forms refer to constructors of the Attr class, one that takes a String argument and another that takes a String and an Object. When a constructor or method is overloaded you must specify the arguments of the one you mean.

The next @see form directs readers to a specific package: com.magic.attr.

The final two forms allow you to reference other documentation. The first defines a link using <a...>. The second uses quotes to enclose the name of the document. You might use these to direct readers to other documentation, such as the full specification.

The @see forms that name a language entity (any of the above forms except the last two) can have a label following the entity. This label name will be the one used in the generated documentation instead of the entity's name. For example,

@see #getName Attribute Names

will create a link to the documentation of getName but will display the text "AttributeNames" not "getName". You should usually let the actual member name be used, but occasionally you may find this feature useful.

{@link} and {@linkplain}

The @see tag is useful for a “See also” section at the end of the documentation. You can embed an {@link} in-line tag in your text when the cross reference should belong in the text of your comment. The syntax for @link is

{@link package.class#member [label]}

The identifier specification is the same as for @see, as is the optional label. The following sentence embeds a link to the getValue method:

Changes the value returned by calls to {@link #getValue}.

The {@linkplain} tag acts just like {@link} except that the generated text uses a plain font rather code font. This is useful for replacing the link with a label that consists of plain text.

@param

The @param tag documents a single parameter to a method or constructor, or else a type parameter in a class, interface, or generic method. If you use @param tags you should have one for each parameter of the method. The first word of the paragraph is taken as the parameter name, and the rest is its description:

@param max    The maximum number of words to read.

When documenting type parameters you should use < and > around the type parameter name:

@param <E>  The element type of this List

Usually, though, type parameters don't require explicit documentation since their meaning is obvious.

@return

The @return tag documents the return value of a method:

@return       The number of words actually read.

@throws and @exception

The @throws tag documents an exception thrown by the method or constructor. If you use @throws tags you should have one for each type of exception the method throws. This list often includes more than just the checked exceptions that must be declared in the throws clause—it is a good idea to declare all exceptions in the throws clause whether or not they are required, and the same is true when you're using @throws tags. For example, suppose that your method checks its parameters to ensure that none is null, throwing NullPointerException if it finds a null argument. You should declare NullPointerException in your throws clause and your @throws tags.

@throws UnknownName   The name is unknown.
@throws java.io.IOException
            Reading the input stream failed; this exception
            is passed through from the input stream.
@throws NullPointerException
          The name is <code>null</code>.

The tag @exception is equivalent to @throws.

@deprecated

The @deprecated tag marks an identifier as being deprecated: unfit for continued use. Code using a deprecated type, constructor, method, or field may generate a warning when compiled. You should ensure that the deprecated entity continues working so that you don't break existing code that hasn't yet been updated. Deprecation helps you encourage users of your code to update to the latest version but preserves the integrity of existing code. Users can shift to newer mechanisms when they choose to instead of being forced to shift as soon as you release a new version of your types. You should direct users to a replacement for deprecated entities:

/**
 * Do what the invoker intends.  "Intention" is defined by
 * an analysis of past behavior as described in ISO 4074-6.
 *
 * @deprecated  You should use dwishm instead
 * @see         #dwishm
 */
@Deprecated
public void dwim() throws IntentUnknownException;

While the compiler may generate a warning if it sees the @deprecated tag, it is guaranteed to generate a warning if it sees the @Deprecated annotation. You should always use the two together: Use the @deprecated tag to document the reason for the deprecation, and use the @Deprecated annotation to inform the compiler.

@author

The @author tag specifies an author of a class or interface.

@author Aristophanes
@author Ursula K. LeGuin
@author Ibid

You can specify as many @author paragraphs as you desire. You should use only one author per @author paragraph to get consistent output in all circumstances.

@version

The @version tag lets you specify an arbitrary version specification for the class or interface.

@version 1.1

@since

The @since tag lets you specify an arbitrary version specification that denotes when the tagged entity was added to your system.

@since 2.1

Tagging the “birth version” can help you track which entities are newer and therefore may need intensified documentation or testing. By convention an @since tag on a class or interface applies to all members of the class or interface that don't have their own @since tag. For example, if the above @since tag preceded a class, then all constructors, fields, and methods of that class would be presumed to have been present in version 2.1 except any that had, for example, an @since2.2 tag of its own.

{@literal} and {@code}

The {@literal text} in-line tag causes text to be printed exactly as is, without being interpreted as HTML source. This means that you can use &, <, and > rather than &amp;, &lt;, and &gt;.

The {@code text} in-line tag behaves exactly like {@literal text} except that text is printed in code font. You'd get the same effect wrapping the {@literal text} tag in <code> and </code> HTML tags.

These in-line tags are exceedingly convenient for writing about generic types.

{@value}

The {@value static-field-name} tag is replaced by the actual value of the specified constant static field. This tag uses the same member syntax as the @see tag. For example, if a doc comment contained the text:

The valid range is 0 to {@value java.lang.Short#MAX_VALUE}.

Then the generated text would be

The valid range is 0 to 32767.

As a convenience, the value of the constant static field being documented can be referred to by {@value}, with no field name. For example, given

/** The default capacity of a new queue ({@value}). */
static final int DEFAULT_CAPACITY = 10;

the generated text would be

The default capacity of a new queue (10).

When specifying a particular field member, be careful not to leave any whitespace between the member name and the closing } because it will be treated as part of the name.

All constant fields are documented on the “Constant Field Values” page, generated by the javadoc tool.

{@docRoot}

The files generated by javadoc are put into a tree, with subdirectories that contain parts of the documentation. The exact placement of files in the tree is up to the javadoc implementation, and may change depending on your environment, user preferences, and the like. You may want to add things to the tree after it is built and then refer to those added pieces in your doc comments.

The in-line {@docRoot} tag lets you put into your doc comments a relative reference to other files in the documentation tree. The {@docRoot} tag will be replaced with a relative path to the top of the generated documentation tree. For example, the sentence

Check out <a href="{@docRoot}/license.html">our license</a>.

would result in a sentence with a link to the file license.html in the root of the documentation tree. After generating the documentation from the doc comments, you could copy license.html into the top of the generated documentation tree, and the above link would always go from the generated output to your license.html file. For some applications you may find the mechanism described in “The doc-files Directory” on page 497 more useful.

{@inheritDoc}

The {@inheritDoc} tag copies a documentation comment from the supertype. This is discussed in the next section.

Inheriting Method Documentation Comments

If no doc comment is given for an inherited method, the method “inherits” the doc comment from the supertype. This is often quite enough, especially when a class implements an interface—methods in the implementation often do nothing more than what the interface specifies, or at least nothing that belongs in a doc comment. It would be inconvenient, to say the least, if you had to duplicate all the doc comments from an interface or superclass to the class that defines the overriding method.

You should put in an explicit comment when you are inheriting doc comments so that someone reading your code doesn't think that you forgot to document the method, for example:

// inherit doc comment
public void dwim() throws IntentUnknownException {
    // ...
}

While overriding an interface method might not require any changes to the documentation, there is a good chance that overriding a superclass method involves changes to the method contract—such as weakening the precondition on a parameter, strengthening the postcondition on a return value, or reducing the types of exception that can be thrown. To make it easier to change only those parts of the documentation that need changing, the block tags define separate entities that can be inherited independently:

  • The main doc comment for the method is known as the body comment. If you don't provide a body comment you will inherit the complete body comment from the supertype. If you provide any text as a body comment, then you won't inherit any part of the supertype's body comment.

  • Each @param comment is inherited independently, based on the name of the parameter. If you don't provide an @param comment for a parameter, then you'll inherit the @param comment from the supertype.

  • If no @return comment is specified then the @return comment from the supertype is inherited.

  • There are special rules for @throws comments, as discussed below.

If a method inherits doc comments from both a superclass and superinterface the interface comment is used.

Often, the change to a doc comment only involves the addition of extra information. For example, an overriding method might guarantee that it never returns null, where the parent method could return null. To avoid manually copying the doc comment from the supertype, you can use the {@inheritDoc} tag to copy the doc comment from the supertype. The {@inheritDoc} tag can appear either in the body comment or within any of the block tags, and it copies the entire supertype's doc comment for that entity. For example, the method that no longer returns null could have a doc comment like this:

/**
 * @return  {@inheritDoc}
 * This implementation never returns null.
 */

The {@inheritDoc} tag allows you to easily add new documentation before or after the inherited documentation, but its effectiveness depends on how the original documentation was written. For example, if the previous method's original @return comment was

@return The value last set, or null if it has not been set.

then the additional documentation results in a less than clear description:

Returns: The value last set, or null if it has not been set.
          This implementation never returns null.

For the sake of clarity, it might be better to rewrite the entire doc comment rather than try to augment it.

Inheriting @throws Comments

There is a special rule for inheriting @throws comments: An overriding method only inherits the @throws comments for exceptions listed in its throws clause, and that are documented by the overridden method. For example, if the original method has an @throws comment for IOException and the overriding method declares that it throws IOException, then the comment is inherited. However, if the overriding method declares that it throws FileNotFoundException (a subclass of IOException) then the comment is not inherited because that exception type is not documented by the overridden method. This restriction on when inheritance of the @throws comment occurs is necessary because automatically inheriting @throws comments is often the wrong thing to do. Unfortunately, not inheriting them can also be the wrong thing to do.

An overriding method can throw fewer checked exceptions than the method it overrides, but not more. So automatically inheriting @throws comments for a checked exception that is not actually thrown would be the wrong thing to do. For checked exceptions it makes sense to inherit the documentation comments only for those exceptions listed in the throws clause. They are, after all, the only checked exceptions that can be thrown. So you inherit the comment if you still throw the exception and you don't inherit the comment if you don't.

Runtime exceptions, which are not typically declared in the throws clause, add a twist to the situation. You usually want to inherit @throws comments for exceptions like IllegalArgumentException because what is illegal for the method you override is typically illegal for your method—so if you don't automatically inherit the comment the exception won't be documented and that is wrong. But then consider, for example, an interface with optionally implemented methods that declare that they throw UnsupportedOperationException. This runtime exception is documented by an @throws comment. If the comment is automatically inherited then even if a particular class's implementation supports the operation and so never throws the exception, the exception will be documented as being thrown—which, again, is wrong.

By requiring that exceptions be listed in the throws clause before inheriting the associated @throws comment, the problem with inheriting inapplicable @throws comments is avoided. However, this promotes a style of programming where runtime exceptions are listed in a method's throws clause, which goes against standard practice. We recommend that you continue to list only checked exceptions in the throws clause of a method. Rather than trying to automatically inherit the doc comments for unchecked exceptions, we suggest that you manually rewrite the @throws comment, but use {@inheritDoc} to avoid the need to manually copy the exception description. For example, you can use the following to document that your method will still throw IllegalArgumentException when it's parent would:

@throws IllegalArgumentException {@inheritDoc}

The onus is still on you to remember that unchecked exceptions must be manually documented in this way.

A Simple Example

The following is a version of the Attr class from page 76 with an example of javadoc comments:

/**
 * An <code>Attr</code> object defines an attribute as a
 * name/value pair, where the name is a <code>String</code>
 * and the value an arbitrary <code>Object</code>.
 *
 * @version 1.1
 * @author Plato
 * @since 1.0
 */
public class Attr {
    /** The attribute name. */
    private final String name;
    /** The attribute value. */
    private Object value = null;

    /**
     * Creates a new attribute with the given name and an
     * initial value of <code>null</code>.
     * @see Attr#Attr(String,Object)
     */
    public Attr(String name) {
        this.name = name;
    }

    /**
     * Creates a new attribute with the given name and
     * initial value.
     * @see Attr#Attr(String)
     */
    public Attr(String name, Object value) {
        this.name = name;
        this.value = value;
    }

    /** Returns this attribute's name. */
    public String getName() {
        return name;
    }

    /** Returns this attribute's value. */
    public Object getValue() {
        return value;
    }

    /**
     * Sets the value of this attribute.  Changes the
     * value returned by calls to {@link #getValue}.
     * @param newValue  The new value for the attribute.
     * @return  The original value.
     * @see #getValue()
     */
    public Object setValue(Object newValue) {
        Object oldVal = value;
        value = newValue;
        return oldVal;
    }

    /**
     * Returns a string of the form <code>name=value</code>.
     */
    public String toString() {
        return name + "='" + value + "'";
    }
}

For simple methods like getName, whose whole description is what it returns, the @return tag is often omitted as overkill. Similarly, the constructors do not use @param tags because the description is sufficiently complete. Different organizations will make different choices of when to use each tag.

You should use doc comments to document all members, including private and package-accessible ones. Documentation generators such as javadoc let you specify whether you want to generate documentation from these comments. Having organized, readable documentation of your class's internals is quite useful when someone else needs to learn about them.

On the following two pages, you can see how the generated HTML javadoc output might look for this class.

A Simple Example
A Simple Example

Exercise 19.1Add doc comments to your LinkedList class from Exercise 2.16. Generate the javadoc and ask someone else to write a simple program using your class. Repeat, improving your doc comments if needed, until someone can do so.

Exercise 19.2Expand on Exercise 19.1 by including the private members. Generate the full (private members included) javadoc and ask someone else to explain the class to you. Repeat, improving your comments if needed, until someone can do so.

External Conventions

Not all documentation needed for a package can be ascribed to a specific source file, nor are source files the only types of files that need to be referred to in documentation. You can incorporate such external elements in your documentation.

Package and Overview Documentation

Doc comments associate documentation with elements in source files, but packages are not defined in source files. The javadoc tool uses other conventions to allow packages to be documented.

The preferred mechanism, as mentioned in Section 18.5 on page 476, is to use the package-info.java file. This file should contain a single package statement identifying the package to which the file belongs, together with all annotations that apply to the package. In addition, if that package statement (with its applied annotations if any) is preceded by a doc comment, then that doc comment is treated as documentation for the overall package. This package documentation forms part of the package summary page that is produced by javadoc.

If there is no package-info.java file for a package, then javadoc will look for a file called package.html. If this file exists, then its contents between <body> and </body> will be read as if it were a doc comment for the package (although it should not have the /**, */, or any leading *). Note that package.html will be ignored if package-info.java exists.

As with other doc comments, the first sentence of the package comment is used as a summary for the package. In the case of package.html, this is the first sentence after the <body> HTML tag. Any @see or {@link} tag that names a language element must use the fully qualified form of the entity's name, even for classes and interfaces within the package itself.

Finally, you can also provide an overview HTML file. An overview HTML file is read in the same way as a package.html file, and it can contain documentation for a set of packages or classes, giving an overview of what they do. You specify the HTML file to use as an overview when generating the documentation.

The doc-files Directory

The javadoc program will copy the contents of a doc-files directory in a given package into the generated documentation for that package. You can use this feature to include images, HTML, class files, or any other component you want to reference in your doc comment. For example, you could indirectly include a set of formal rules in a large number of doc comments:

@see <a href="doc-files/semantics.html">Formal Semantics</a>

Or you could use the directory to store useful images:

Made by Magic, Inc.<img src="doc-files/magiclogo.gif">

Notes on Usage

Tightly coupling the reference documentation to the source code has many advantages, but it does not turn all programmers into good documentation writers. Programmers will continue to vary in their ability and interest in writing good reference documentation. Many organizations have technical writers to produce the reference documentation. Doc comments require write access to the source, and technical writers often do not have permission to modify source code. The use of doc comments will require a change in such organizations.

Another issue is comment skew, in which comments become out of date as the source code changes over time. You can reduce this problem by putting only contractual information in your doc comments and not describing the implementation. When the implementation changes, the doc comment will still be correct as long as the contract remains unmodified. Changing the contract of an existing type, constructor, method, or field is a questionable practice in many cases, so such changes should be rare. Describing only the contract is generally a good practice in any case because it frees you to change details of the implementation in the future. Implementation details of methods need to be documented—use regular comments for this purpose.

You can further reduce the problem of comment skew by defining a standard marker for programmers to place in doc comments that need attention. For example, if you add a new method to a class, you could write the first draft of the doccomment, but flag the comment as one that might need review and rework by the documentation team:

/**
 * ...initial draft...
 * @docissue Review -- programmer's first draft
 */

A script run over the source could find @docissue markers and show them to the documentation team, alerting them to work that remains to be done. Some documentation generators allow you to add your own doc comment paragraph tags, so using an @ tag—such as @docissue shown above—allows you to flag these or other issues directly in the generated documentation as well as in the source itself.

 

The universe is made of stories, not atoms.

 
 --Muriel Rukeyser


[1] This distinction is blurring and, for better or worse, documentation comments are being used to define full specifications.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.233.43