Java's three kinds of comment and who each is written for, how to read a library class's documentation page — signature, returns, throws — and how to write your own so that the javadoc tool turns it into exactly the same kind of page. Follows Think Java 2e, Chapter B (Javadoc), Sections B.1-B.5, pp. 309-318, cross-referenced against Oracle — How to Write Doc Comments for the Javadoc Tool.
Subject: Java · 65 slides · code lesson
Open the interactive version of this deck
Title
Think Java 2e · Chapter B · Javadoc
Sections B.1-B.5 · pp. 309-318
Objectives
This lesson follows Think Java 2e, Chapter B (Javadoc), Sections B.1-B.5, pp. 309-318. Everything on these slides can be checked against those pages.
1. Distinguish end-of-line, multiline and documentation comments, and say who each is for.
2. Navigate a library class's documentation and find what a method returns and what it throws.
3. Write a documentation comment for a class and for a method.
4. Use the @author, @version, @param and @return tags correctly.
5. Explain why a @return tag should not name the return type.
6. Run the javadoc tool to generate HTML documentation.
Warm-up
Three things you have been doing without a name for it.
Discussion prompt
From Lesson 1b: what is a comment, and what does the compiler do with one? From Lesson 3a: which library class did you use to read input? And from Lesson 17a: what happens when a method's argument is invalid?
Hint: It is ignored entirely. And an exception is thrown.
Answer:
A comment is text for people, and the compiler ignores it completely. Scanner, from java.util, reads input. And an invalid argument can cause the method to throw an exception.
All three appear here. A nice feature of the Java language is the ability to embed documentation in the source code itself. That way, you can write it as you go, and as things change, it is easier to keep the documentation consistent with the code.
Concept
Java programs have three types of comments, and the difference that matters is not the syntax — it is who each one is written for.
Figure (svg): Two panels separating comments written for yourself from documentation written for other people
Downey & Mayfield, Think Java, 2nd edition (Green Tea Press / O'Reilly, 2020) — Think Java 2e, Chapter B (Javadoc), Sections B.1-B.5, pp. 309-318 — Appendix B begins on printed page 309.
Section
Appendix opener
Concept
The three forms differ by two characters, and the difference decides whether a tool will read them.
// End-of-line comments start with two slashes
/* Multiline comments start with slash-star
and end with star-slash */
/**
* Documentation comments start with slash-star-star
* and end with star-slash.
*/| form | used for | read by javadoc? |
|---|---|---|
| // ... | short phrases explaining specific lines | no |
| /* ... */ | typically copyright statements | no |
| /** ... */ | what each class and method does | yes |
documentation — Comments that describe the technical operation of a class or method.
Javadoc — A tool that reads Java source code and generates documentation in HTML format.
End-of-line and multiline comments are written primarily for yourself. They help you remember specific details about your source code. Documentation comments, on the other hand, are written for others. They explain how to use your classes and methods in other programs.
Notation
It could live in a separate manual. The appendix explains why it does not.
Annotate
The library's documentation is not a special artefact. Somebody wrote a /** comment above nextInt, and a tool turned it into the page you look up.
Worked example
A professional source file uses all three, in a particular order.
/*
* Copyright (c) 2019 Allen Downey and Chris Mayfield
* ... the MIT License ...
*/
import java.util.Scanner;
/**
* Methods for converting to/from the metric system.
*/
public class Convert {
public static double toMetric(int feet, int inches) {
int total = feet * IN_PER_FOOT + inches; // to inches
return total * CM_PER_INCH;
}
}| comment | form | why that form |
|---|---|---|
| the copyright | /* */ | not documentation — should not appear in the HTML |
| the class description | /** */ | documentation — it should |
// to inches | // | a note about one line, for a maintainer |
The copyright comes first.
Why: Professional-grade source files often begin with a copyright statement.
And it uses a plain multiline comment.
Why: *This text spans multiple lines, but it is not part of the documentation. So we use a multiline comment (/) rather than a documentation comment (/).
Imports come next.
Why: Import statements generally follow the copyright text.
Then the class documentation, touching the class.
Why: After that, we can define the class itself and begin writing the documentation.
Verify: Ask what would happen if the licence used /** instead of /*.
Why: The entire MIT License would appear at the top of the generated HTML page, before anything useful. One character decides whether text is documentation — which is why the distinction is worth being deliberate about.
Prediction
The opening delimiter decides.
/** ... */
/* ... */| opens with | javadoc reads it? |
|---|---|
| /** | ? |
| /* | no |
Predict first
Which one is a documentation comment?
Correct: /** — two stars to open, one to close
Why: They begin with / (two stars) and end with / (one star).* The asymmetry is worth noticing — the closing delimiter is the same for both kinds, so only the opening tells you which you are reading.
Concept
Javadoc comments are longer, usually complete sentences. They explain what each method does, but they omit details about how the method works.
| end-of-line | documentation | |
|---|---|---|
| length | short phrases | usually complete sentences |
| explains | how a tricky line works | what the method does |
| audience | someone reading the source | someone calling the method |
| assumes you can see the code | yes | no |
They are intended for people who will use the methods without looking at the source code. That last row is the practical test: if your documentation comment only makes sense to someone reading the body, it is an end-of-line comment in the wrong place.
Trap
Documentation that says what the signature already says.
/**
* This method is called toMetric. It takes an int called
* feet and an int called inches and returns a double.
*
* @return double
*/
public static double toMetric(int feet, int inches) {| the comment says | the reader already knew |
|---|---|
| the method is called toMetric | yes — it is right there |
| it takes two ints | yes |
| it returns a double | yes |
| what it actually does | never mentioned |
Comments like @return boolean are not useful, because you already know the return type from the method's signature. Every line here is true and none of it helps.
Say what the signature cannot.
/**
* Converts a length in feet and inches to centimeters.
*
* @param feet how many feet
* @param inches how many inches
* @return length in centimeters
*/
public static double toMetric(int feet, int inches) {| the comment adds | which the signature omits |
|---|---|
| it converts to centimetres | the units |
| feet means how many feet | the meaning of a bare int |
| the result is a length in cm | what the double represents |
A double is not a length in centimetres until somebody says so. The signature gives you types; the documentation gives you meaning — which is exactly the gap Lesson 12a's encoding argument identified.
Definition probe
Three forms, three purposes.
Sort into buckets
Sort each piece of text.
Fill the middle
Two stars to open.
Fill in the blanks
/**
* Prints a greeting.
*/
public static void main(String[] args) {
Why: Two stars open a documentation comment and one closes it. The leading * on the middle lines is conventional formatting rather than syntax — javadoc strips it, and the comment would work without it.
Explain it to yourself
The appendix draws a sharp line.
Discussion prompt
End-of-line comments are written primarily for yourself; documentation comments are written for others. What follows from that about how each should be written?
Hint: What can each reader see?
Answer:
A reader of an end-of-line comment can see the code. So it can be a fragment, use local variable names, and assume everything around it.
A reader of documentation cannot. They have a signature and your sentences — so the sentences have to be complete, and to explain what, not how.
And remember that the person most likely to read your code in the future, and appreciate good documentation, is you. In six months you are the person who cannot see the code any more.
Section
Section B.1
Concept
**As an example, let's look at the documentation for Scanner, a class we first used in Section 3.2. You can find the documentation quickly by doing a web search for Java Scanner.**
| part of the page | tells you |
|---|---|
| the first line | the package, such as java.util |
| the second line | the name of the class |
| All Implemented Interfaces | some of the functionality it has |
| the narrative | the purpose of the class, with examples |
| Constructor Summary | ways of creating one |
| Method Summary | the list of methods it provides |
| Constructor Detail and Method Detail | more information about each |
Documentation for other classes uses a similar format. Once you have found your way around one page you can find your way around all of them, which is most of the value of a standard format.
Notation
The appendix is honest that the narrative is often the hardest part, and gives a way in.
Annotate
Learning which parts to ignore is named as a skill, which is unusual and correct. A reference page is not meant to be read start to finish.
Worked example
One of the examples shows how you can use a Scanner to read input from a String instead of System.in.
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input);| constructor argument | reads from |
|---|---|
| System.in | the keyboard |
| a String | the text of that string |
| a File | a file — Exercise 15.3 used this |
Every Scanner you have written took System.in.
Why: Lesson 3a onward, without exception.
The documentation shows another constructor.
Why: It takes a String and reads tokens from it.
Which is immediately useful for testing.
Why: A test can supply input without any redirection at all.
And you would never have guessed it.
Why: Nothing in the code you have written hints that this exists.
Verify: Note that this is Lesson 11a's overloading again: several constructors, distinguished by parameter type.
Why: Knowing what's available in the library helps you avoid reinventing the wheel. And a little bit of documentation can save you a lot of debugging. This one constructor makes unit-testing input-reading code straightforward, and the only way to find it is to look.
Prediction
The documentation is explicit about this.
public int nextInt()| part | in the signature? |
|---|---|
| the name | yes |
| the parameters | yes |
| the return type | ? |
Predict first
Is int part of nextInt's signature?
Correct: No — the signature is the name and parameters only
Why: The first line is the method's signature, which specifies the name of the method and its parameters. The type it returns (int) is not part of the signature. That is why overloading works on parameter lists — two methods differing only in return type would have the same signature and could not coexist.
Concept
For example, here is the summary information for nextInt. The Method Detail says more.
public int nextInt()
Scans the next token of the input as an int.
Returns:
the int scanned from the input
Throws:
InputMismatchException - if the next token does not match
the Integer regular expression, or is out of range
NoSuchElementException - if input is exhausted
IllegalStateException - if this scanner is closed| section | describes |
|---|---|
| the first line | the signature — the name and parameters |
| the next line | a short description of what it does |
| Returns | the result when the method succeeds |
| Throws | possible errors and exceptions |
signature — The first line of a method that defines its name and parameters.
The first line is the method's signature, which specifies the name of the method and its parameters (none). The type it returns (int) is not part of the signature. That last clause matters: Java distinguishes overloaded methods by parameters, never by return type.
Trap
Reading only what a method returns.
int n = in.nextInt(); // what if the user types "hello"?
// Throws:
// InputMismatchException - if the next token does not
// match the Integer regular expression
// NoSuchElementException - if input is exhausted| input | result |
|---|---|
| 42 | returns 42 |
| hello | InputMismatchException |
| nothing — end of input | NoSuchElementException |
The Returns section describes the result when the method succeeds. In contrast, the Throws section describes possible errors and exceptions that may occur. Reading only the first half leaves you surprised by the second.
Read both, and decide what you will do about each.
// having read the Throws section, you can choose:
if (in.hasNextInt()) {
int n = in.nextInt();
} else {
System.out.println("Please enter a number.");
}| question | which section answers it |
|---|---|
| what do I get back? | Returns |
| what can go wrong? | Throws |
| how do I avoid it? | the Method Summary — hasNextInt |
Exceptions are said to be thrown, like a referee throwing a flag, or like a toddler throwing a fit. Reading the Throws section is how you discover both the failure modes and, usually, the method that lets you check first.
Definition probe
A documentation page has a standard layout.
Sort into buckets
Sort each question by where it is answered.
Prediction
An example from Scanner's own documentation.
String input = "1 fish 2 fish red fish blue fish";
Scanner s = new Scanner(input);| argument | source of input |
|---|---|
| System.in | the keyboard |
| a String | ? |
Predict first
Where does this Scanner read from?
Correct: The contents of the string, as if they had been typed
Why: Scanner has several overloaded constructors, and this one tokenises the string itself. It is immediately useful for testing input-handling code without redirection — and there is no way to discover it except by reading the documentation.
Real world
You could just try things and see what happens.
Discussion prompt
Trial and error works for simple methods. What does reading the documentation give you that experimenting does not?
Hint: What did you not think to try?
Answer:
The methods you did not know existed. Experiment with nextInt all day and you will never discover hasNextInt, or the String constructor, or half of what the class offers.
And the failure cases. Your experiments use inputs you thought of; the Throws section lists the ones the author thought of, including several you would meet only in production.
A little bit of documentation can save you a lot of debugging — and its counterpart, knowing what's available in the library helps you avoid reinventing the wheel, is the bigger saving of the two.
Section
Section B.2
Concept
As you benefit from reading good documentation, you should pay it forward by writing good documentation.
/**
* Example program that demonstrates print vs println.
*/
public class Goodbye {
/**
* Prints a greeting.
*/
public static void main(String[] args) {
System.out.print("Goodbye, "); // note the space
System.out.println("cruel world");
}
}| comment | documents | says |
|---|---|---|
| the first /** */ | the class | its purpose |
| the second /** */ | the main method | what the method does |
| the // comment | one line | why there is a space |
Javadoc scans your source files looking for documentation comments, also known as Javadoc comments. The class comment explains the purpose of the class. The method comment explains what the method does — and note that both sit immediately above what they describe, which is how javadoc knows what they belong to.
Notation
The distinction between the two kinds of comment is made precisely here.
Annotate
**Documenting what rather than how is the same argument as encapsulation.** Lesson 11a hid the implementation so it could change; documenting only the interface keeps the comment true when it does.
Worked example
Javadoc attaches a comment to whatever declaration follows it, which makes one mistake very easy.
// WRONG - the import separates the comment from the class
/**
* Methods for converting to/from the metric system.
*/
import java.util.Scanner;
public class Convert {
// RIGHT - the */ "touches" the word public
import java.util.Scanner;
/**
* Methods for converting to/from the metric system.
*/
public class Convert {| what follows the comment | what gets documented |
|---|---|
| public class Convert | the class — correct |
| an import statement | nothing useful |
| a method declaration | that method |
| a blank line then a method | still that method |
Javadoc attaches to the next declaration.
Why: Which is why position is not a matter of taste.
A common beginner mistake.
Why: A common mistake that beginners make is to put import statements between the documentation and the public class line.
And the consequence.
Why: Doing so separates the documentation from the class itself.
The rule of thumb.
Why: **To avoid this issue, always make the end of the comment (the /) touch the word public.*
Verify: Notice that imports go above the class documentation, and the copyright above them.
Why: Copyright, then imports, then the class documentation, then the class. That order is not arbitrary — each comment must be adjacent to what it documents, and the licence deliberately documents nothing.
Prediction
Javadoc attaches to the next declaration.
/**
* Methods for converting to/from the metric system.
*/
import java.util.Scanner;
public class Convert {| after the comment comes | so it documents |
|---|---|
| an import | ? |
Predict first
What is wrong here?
Correct: The import separates the comment from the class, so the class is undocumented
Why: **A common mistake that beginners make is to put import statements between the documentation and the public class line. Doing so separates the documentation from the class itself. To avoid this issue, always make the end of the comment (the /) touch the word public.*
Concept
The methods, on the other hand, could use some explanation. Each documentation comment includes a description, followed by a blank line, followed by a @param tag for each parameter, followed by a @return tag.
/**
* Converts a length in feet and inches to centimeters.
*
* @param feet how many feet
* @param inches how many inches
* @return length in centimeters
*/
public static double toMetric(int feet, int inches) {
int total = feet * IN_PER_FOOT + inches;
return total * CM_PER_INCH;
}| line | part |
|---|---|
| Converts a length in feet and inches to centimeters. | the description |
| (blank) | separates description from tags |
| @param feet how many feet | one tag per parameter |
| @param inches how many inches | each on its own line |
| @return length in centimeters | what comes back, and in what units |
description — The first line of a documentation comment that explains what the class/method does.
The constants are self-explanatory, so there is no need to write documentation for them. CM_PER_INCH needs no comment; a method taking two bare ints does. Documentation is for what the code cannot say for itself.
Trap
A comment describing what the method used to do.
/**
* Converts a length in inches to centimeters.
*
* @param inches how many inches
* @return length in centimeters
*/
public static double toMetric(int feet, int inches) {
// the method was changed to take feet as well;
// the comment was not
}| the comment says | the code does | |
|---|---|---|
| parameters | one | two |
| @param feet | missing | exists |
| is it checked? | not by the compiler | — |
Wrong documentation is worse than none, because it is believed. A missing comment makes the reader look at the code; an incorrect one stops them looking.
Change the comment in the same edit as the code.
/**
* Converts a length in feet and inches to centimeters.
*
* @param feet how many feet
* @param inches how many inches
* @return length in centimeters
*/
public static double toMetric(int feet, int inches) {| habit | why it works |
|---|---|
| the comment sits above the method | you cannot edit one without seeing the other |
| change both at once | there is no later to forget |
| run Checkstyle | it catches a missing @param — Lesson A |
This is why the language embeds documentation in the source at all — as things change, it is easier to keep the documentation consistent with the code. The proximity is the mechanism, and it only works if you use it.
Definition probe
Not everything does.
Sort into buckets
Sort each declaration.
Fill the middle
Description, blank line, tags.
Fill in the blanks
/**
* Converts a measurement in centimeters to inches.
*
* @param cm length in centimeters
* @return length in inches
*/
public static double toImperial(double cm) {
Why: One @param per parameter, naming it and saying what it means, then one @return describing what comes back. Note both mention units — which is exactly the information the signature's double cannot carry.
Socratic
The how is often the interesting part.
Discussion prompt
A documentation comment explains what a method does and omits how it works. Why leave out the part you probably found hardest to write?
Hint: Who is reading, and what happens when you rewrite the body?
Answer:
Because the reader is not looking at the body. They want to know whether to call it and what they will get — the algorithm inside is not their problem.
And because the body changes. Replace a linear search with a binary one and every how sentence is now wrong, while every what sentence still holds.
Document the contract, not the implementation — which is Lesson 11a's encapsulation argument exactly. If the how is genuinely hard, that is what end-of-line comments inside the body are for.
Section
Section B.3
Concept
It's generally a good idea to document each class and method, so that other programmers can understand what they do without having to read the code. To organize the documentation into sections, Javadoc supports optional tags that begin with the at sign.
/**
* Utility class for extracting digits from integers.
*
* @author Chris Mayfield
* @version 1.0
*/
public class DigitUtil {| tag | documents |
|---|---|
| @author | who wrote it — may appear more than once |
| @version | which version this is |
| @param | one parameter |
| @return | the return value |
tag — A label that begins with an at sign (@) and is used by Javadoc to organize documentation into sections.
**Documentation comments should begin with a description of the class or method, followed by the tags. These two sections are separated by a blank line (not counting the ).*
Notation
Each is a small thing that produces a visibly wrong page when ignored.
Annotate
main's comment has only a @param.Every one of these rules exists because the tool adds something. Knowing that javadoc generates the hyphen, the Parameters: heading and the Returns: heading explains all five at once.
Worked example
Notice the relationship between the Javadoc comment (in the source code) and the resulting documentation (in the HTML page).
/**
* Tests whether x is a single digit integer.
*
* @param x the integer to test
* @return true if x has one digit, false otherwise
*/
public static boolean isSingleDigit(int x) {| in the source | on the page |
|---|---|
| the method signature | isSingleDigit / public static boolean isSingleDigit(int x) |
| the description | Tests whether x is a single digit integer. |
| @param x the integer to test | Parameters: x – the integer to test |
| @return true if x has one digit, false otherwise | Returns: true if x has one digit, false otherwise |
The signature is taken from the code.
Why: Not from the comment — which is why it is always accurate.
The description becomes the summary line.
Why: First sentence first, as with the library pages you read.
Each @param becomes a row under Parameters.
Why: With the hyphen supplied by the tool.
@return becomes the Returns section.
Why: The same layout as nextInt's page.
Verify: Compare this generated page with the nextInt page from Section B.1.
Why: They are the same format because they were produced by the same tool from the same kind of comment. The library's documentation is not privileged — it is /** comments in Scanner.java, run through javadoc.
Prediction
The method takes two parameters.
public static double toMetric(int feet, int inches)| parameters | @param tags |
|---|---|
| 2 | ? |
Predict first
How many @param tags should the comment have?
Correct: Two — one per parameter, each on its own line
Why: Methods with multiple parameters should have separate @param tags that describe each one. Each tag should be on its own line in the source code — which keeps the generated table readable and gives each parameter its own row.
Concept
Here are two ways you can run the Javadoc tool on this example program.
javadoc -d doc Convert.java| part | means |
|---|---|
| javadoc | the tool, included with the JDK |
| -d doc | generate the HTML files into a directory named doc |
| Convert.java | the source file to read |
The -d option of javadoc indicates where to generate the HTML files. Or from DrJava, click the Javadoc button on the toolbar — and any IDE has an equivalent. For more examples of what you can do with Javadoc comments, see the source code of any Java library class — which Lesson 10b showed you how to find.
Trap
Two small mistakes that both show up in the output.
/**
* Tests the conversion methods.
*
* @param args - command-line arguments
* @return void
*/
public static void main(String[] args) {| mistake | what the page shows |
|---|---|
| the hyphen after @param | args – – command-line arguments |
| @return on a void method | a Returns section for nothing |
| @return void | the type, which the signature already gave |
Neither is an error — javadoc generates the page regardless. They are mistakes you only notice by looking at the output, which is a good reason to generate it at least once.
No hyphen, and no @return on a void method.
/**
* Tests the conversion methods.
*
* @param args command-line arguments
*/
public static void main(String[] args) {| rule | reason |
|---|---|
| no hyphen after @param | javadoc adds one |
| no @return if void | there is no value to describe |
| describe the value, not the type | the type is in the signature |
The main method has a similar documentation comment, except there is no @return tag since the method is void. One parameter, one tag, and nothing that the signature already said.
Prediction
The method returns a boolean.
/**
* @return boolean
*/
public static boolean isSingleDigit(int x) {| the reader learns | from |
|---|---|
| the return type | the signature |
| what the value means | ? |
Predict first
What is the problem?
Correct: It names the type instead of describing the value, which the signature already gave
Why: Comments like @return boolean are not useful, because you already know the return type from the method's signature. The useful version says what the value means — true if x has one digit, false otherwise — which is the thing the type cannot express.
Matching
Four tags from this appendix.
Match the pairs
Why: The first two document a class; the last two document a method. Note @author may appear more than once — the Convert example has two, one per author, each on its own line.
Edge cases
It's generally a good idea to document each class and method.
Discussion prompt
The appendix says generally. When would a documentation comment add nothing, and what does Checkstyle's Missing a Javadoc comment warning miss about that?
Hint: The Convert constants have none.
Answer:
When the name says everything. CM_PER_INCH = 2.54 is self-explanatory, and the book documents neither constant for exactly that reason.
A private helper is often the same — a two-line method called swapCards(i, j) in a class you can read end to end.
Checkstyle cannot tell the difference, which is Lesson A's point: it checks that a comment exists, not that it helps. The answer to a warning is sometimes a comment and sometimes a better name.
Section
Section B.4
Concept
Now let's take a look at a more complete example. A professional source file has a conventional opening, and every part of it is in that position for a reason.
/*
* Copyright (c) 2019 Allen Downey and Chris Mayfield
* ... MIT License ...
*/
import java.util.Scanner;
/**
* Methods for converting to/from the metric system.
*
* @author Allen Downey
* @author Chris Mayfield
* @version 6.1.5
*/
public class Convert {| position | content | why there |
|---|---|---|
| first | the copyright, in /* */ | legally prominent; not documentation |
| second | imports | before the class, after the licence |
| third | the class documentation, in /** */ | must touch the class |
| fourth | public class | — |
Two @author tags, one per author — a tag may be repeated where that makes sense. And the version is 6.1.5, which is the book's own edition number, quietly.
Picture it
The whole appendix in one pipeline: you write, the tool reads, a reader searches.
Figure (svg): A pipeline from a documentation comment through the javadoc tool to an HTML page a reader searches for
In fact, the official documentation for the Java library is generated by Javadoc. The page you look up when you search Java Scanner began as a comment in Scanner.java.
Worked example
This class has two constants and three methods. Each gets what it needs and no more.
public static final double CM_PER_INCH = 2.54; // no comment needed
public static final int IN_PER_FOOT = 12; // no comment needed
/**
* Converts a measurement in centimeters to inches.
*
* @param cm length in centimeters
* @return length in inches
*/
public static double toImperial(double cm) {
return cm / CM_PER_INCH;
}| member | documented? | why |
|---|---|---|
| CM_PER_INCH | no | self-explanatory |
| IN_PER_FOOT | no | self-explanatory |
| toImperial | yes | a double parameter needs units |
| toMetric | yes | two ints need meanings |
| main | yes, without @return | it is void |
Skip what needs nothing.
Why: The constants are self-explanatory, so there is no need to write documentation for them.
Document what does.
Why: The methods, on the other hand, could use some explanation.
Use the standard shape.
Why: Each documentation comment includes a description, followed by a blank line, followed by a @param tag for each parameter, followed by a @return tag.
Adjust for void.
Why: The main method has a similar documentation comment, except there is no @return tag since the method is void.
Verify: Read toImperial's comment and its body, and notice the comment never mentions dividing by 2.54.
Why: What, not how. The description says it converts centimetres to inches; the division is an implementation detail a caller does not need and a future rewrite might change.
Prediction
It is a long multiline block above the class.
/*
* Copyright (c) 2019 Allen Downey and Chris Mayfield
* ... the MIT License ...
*/| form | appears in the HTML? |
|---|---|
| /* */ | no |
| /** */ | yes |
Predict first
Why not use /** here?
Correct: It is not documentation, so it should not appear in the generated pages
Why: *This text spans multiple lines, but it is not part of the documentation. So we use a multiline comment (/) rather than a documentation comment (/). Using two stars would put the entire licence at the top of the class's HTML page, ahead of anything a reader wants.
Concept
The appendix's closing argument is about maintenance rather than politeness.
| when you write it | what happens |
|---|---|
| as you go | it exists, and matches the code |
| at the end of the project | it is rushed and partly wrong |
| when someone asks | never |
| never | you re-read the body every time |
Appropriate comments and documentation are essential for making source code readable. And remember that the person most likely to read your code in the future, and appreciate good documentation, is you. The first row is only easy because the comment lives three lines from the code it describes.
Trap
Leaving it all until the end.
// forty methods written over three weeks
// now write forty documentation comments in one afternoon
/**
* Does the thing with the list.
*/
public void process(List<Item> items, boolean flag) {| problem | consequence |
|---|---|
| you no longer remember why | the comment describes the code, not the intent |
| forty at once | each gets two minutes |
what is flag? | you would have to read the body to find out |
| so you write | Does the thing with the list |
The comment is worse than nothing: it occupies the space where a real explanation would go. And the one piece of information nobody can recover — what flag was for — is exactly what is missing.
Write it while you still know why.
/**
* Converts a length in feet and inches to centimeters.
*
* @param feet how many feet
* @param inches how many inches
* @return length in centimeters
*/
public static double toMetric(int feet, int inches) {| written | cost | quality |
|---|---|---|
| as you write the method | a minute | accurate |
| three weeks later | ten minutes of re-reading | approximate |
| never | nothing now | paid later, repeatedly |
That way, you can write it as you go, and as things change, it is easier to keep the documentation consistent with the code. The appendix's first paragraph is an argument about when, and it is the part most easily skipped.
Definition probe
Four things, one conventional order.
Sort into buckets
Sort each by position.
Fill the middle
Description, blank line, tags.
Fill in the blanks
/**
* Utility class for extracting digits from integers.
*
* @author Chris Mayfield
* @version 1.0
*/
public class DigitUtil {
Why: @author and @version are class-level tags, separated from the description by a blank line. @author may be repeated — the Convert example has two, one per author, each on its own line.
Real world
Thousands of classes, all documented.
Discussion prompt
Java's library documentation is enormous and generated from comments in the source. What would using the library be like without it, and what does that say about your own code?
Hint: How would you learn what Scanner does?
Answer:
You would have to read the source of every class you used — thousands of lines to discover that nextInt exists, never mind that it can throw three different exceptions.
And you would still miss things. Reading a body tells you what it does today; documentation tells you what it promises, which is what you are actually allowed to rely on.
Your code is somebody's library — including your own, next year. As you benefit from reading good documentation, you should pay it forward by writing good documentation.
Comparison
Fill the blanks.
Comparison matrix
| // end-of-line | /* multiline */ | /** documentation */ | |
|---|---|---|---|
| written for | yourself | yourself | others |
| typical use | explaining one line | copyright statements | what a class or method does |
| read by javadoc | no | no | yes |
| assumes you can see the code | yes | — | no |
| supports @ tags | no | no | yes |
The first row is the one that decides everything else. An end-of-line comment can assume its reader is looking at the code; a documentation comment cannot — so one can be a fragment and the other must be a sentence.
Pattern
A documentation comment: description, blank line, one tag per thing.
/**
* Converts a length in feet and inches to centimeters.
*
* @param feet how many feet
* @param inches how many inches
* @return length in centimeters
*/
public static double toMetric(int feet, int inches) {| rule | reason |
|---|---|
| the */ touches the declaration | javadoc attaches to what follows |
| description first, then a blank line, then tags | the standard layout |
| one @param per parameter, each on its own line | one row each in the output |
| no hyphen after @param | javadoc supplies one |
| no @return on a void method | there is no value to describe |
| describe the value, not the type | the signature gives the type |
javadoc -d doc Convert.java.Check
Work it out before you click.
/**
* ...
*/
/*
* ...
*/| form | purpose |
|---|---|
| /** | ? |
| /* | ? |
Check your understanding
Which is a documentation comment, and what is the other typically used for?
Answer: A
Why: Documentation comments start with / and end with /. Multiline comments start with / and end with /, and are typically used for copyright statements.* The distinction matters because javadoc reads one and ignores the other — putting a licence in /** would print the whole thing at the top of the generated page.
Check
Work it out before you click.
public int nextInt()| part | in the signature? |
|---|---|
| nextInt | yes |
| int | ? |
Check your understanding
What is a method's signature?
Answer: A
Why: The first line is the method's signature, which specifies the name of the method and its parameters (none). The type it returns (int) is not part of the signature. This is why overloading distinguishes methods by their parameter lists: two methods that differed only in return type would have identical signatures and could not both exist.
Check
Work it out before you click.
/**
* Tests the conversion methods.
*
* @param args command-line arguments
*/
public static void main(String[] args) {| method returns | @return tag? |
|---|---|
| void | ? |
Check your understanding
Why is there no @return tag?
Answer: A
Why: Void methods should have no @return tag, since they do not return a value. Note also what the comment does right: @param args command-line arguments with no hyphen, since javadoc adds one when it generates the HTML, and each tag on its own line.
Real world
Java's library documentation is one of the reasons the language spread as far as it did.
Discussion prompt
Why does the quality of a library's documentation matter as much as the quality of its code — and what does that mean for a class you write?
Hint: What can people do with code they cannot understand?
Answer:
Because undocumented code cannot be used by anyone but its author. A perfect method nobody can find or understand is, from outside, the same as no method at all.
And documentation is what makes a promise checkable. Reading the body tells you what the code does today; the documentation tells you what it commits to, which is what you can safely depend on.
Your own classes are libraries for your future self and your teammates. The whole reason Java embeds documentation in the source is to make writing it cheap enough that it actually happens — you can write it as you go.
Commit first
Commit to an answer and to your confidence.
Predict first
Why should a @return tag not name the method's return type?
Correct: Because the signature already gives the type; the tag should describe what the value means
Why: Comments like @return boolean are not useful, because you already know the return type from the method's signature. The useful version says what the value means — true if x has one digit, false otherwise — which is exactly what a type cannot express. That is the same principle behind the whole appendix: documentation supplies what the code cannot say for itself, which is why the constants in Convert need none and a method taking two bare ints does.
Explain it
Two minutes, out loud.
Discussion prompt
A classmate has written a comment above their class and cannot see it in the generated documentation. Walk them through the two most likely causes.
Hint: Count the stars, and look at what comes next.
Answer:
First, count the stars. A documentation comment opens with /** — two — and closes with */. If it opens with one star, javadoc ignores it entirely.
Second, look at what comes immediately after the comment. Javadoc attaches it to the next declaration, so an import statement in between means the comment documents nothing.
The rule of thumb is to make the closing */ touch the word public. Copyright first, then imports, then the documentation comment, then the class — and the licence deliberately uses one star so it does not end up on the page.
Exit ticket
One question before you close the deck.
Predict first
What is the difference between an end-of-line comment and a documentation comment?
Correct: An end-of-line comment explains a specific line for someone reading the source; a documentation comment explains what a class or method does, for people who will use it without reading the source
Why: End-of-line and multiline comments are written primarily for yourself. Documentation comments, on the other hand, are written for others. The audience decides everything else: an end-of-line comment can be a fragment because its reader can see the surrounding code, while a documentation comment must be complete sentences explaining what, not how, because its reader has only the signature and your words. Both are ignored by the compiler; only the /** form is extracted by javadoc into HTML.
Connect it up
One page, from memory.
Draw it
Write out the top of a source file in order — copyright, imports, class documentation, class declaration — using the right comment form for each and marking where the */ must touch. Beside it, write a complete documentation comment for a two-parameter method that returns a value, with a description, a blank line and the tags. Then draw the arrow from each part of that comment to where it appears on the generated HTML page. Finish by listing the five tag rules: no hyphen, no type in @return, one @param each, none for void, one per line.
Recap
Five sections about the comments the compiler ignores and a tool does not.
| if you remember one thing | it is this |
|---|---|
| about reading | start with the examples, and read Throws |
| about writing | what, not how — the reader cannot see the body |
| about when | as you go, while you still know why |
// for yourself, /* */ for copyright, /** */ for others.*/ must touch the declaration it documents.Want this taught 1-on-1? Alexander tutors Java — $55/session, free consultation.