Skip to content
HopperHopper

Course navigation

Unit 1 · Using Objects and MethodsTopic 1.8

Documentation with Comments

  • About 50 minutes
  • 6 sections
  • Runnable Java examples
  • Practice questions

Before you start

About 50 minutes

By the end you will be able to

  1. Explain who comments are written for and why they never change what a program does.
  2. Read and write single-line, block, and Javadoc comments, and predict the output of code that contains them.
  3. Explain how Javadoc comments become a library's documentation, and read the @param and @return lines in them.
  4. State the precondition of a method or code segment, and explain who is responsible for making it true.
  5. State the postcondition of a method or code segment, and tell it apart from a precondition.
Section 1 of 6

1.8.1 Comments Are Notes for People

Open a program you wrote two months ago and you may not remember why a line says quizScore += bonus or what the 2 in int bonus = 2; stands for. Now imagine reading a program someone else wrote. Java code says exactly what the computer does, but it rarely says why. The reasons live in the programmer’s head, and nobody else can see them.

The fix is to write the reasons down, right next to the code, in plain English. Java gives you a way to do this so the compiler does not try to read your English as Java. In Topic 1.1 you saw that the compiler checks every line and translates it before the program runs. Text marked as a note is skipped by the compiler entirely: it is never checked, never translated, and never run.

A comment is text in a program that is written for people to read. Comments help the original programmer (you, later) and other programmers understand what the code does and why. The compiler ignores comments, so they are not part of the running program at all.

Key idea

Comments are notes for people. The compiler ignores them, so adding, removing, or changing a comment never changes what a program does.

The quickest kind of comment starts with two slashes, //: everything from // to the end of that line is a comment. (1.8.2 looks at this kind closely.)

Worked example: The same program with and without comments

Here is a short program with no comments. Read it and ask yourself: what is the 18? What is the 2? Is a score above 20 a mistake?

ScoreReport.java
public class ScoreReport
{
    public static void main(String[] args)
    {
        int quizScore = 18;
        int bonus = 2;
        quizScore += bonus;
        System.out.print("Final quiz score: ");
        System.out.println(quizScore);
    }
}
Final quiz score: 20

Now the same statements with comments added on lines 5, 7, and 9:

ScoreReportCommented.java
public class ScoreReportCommented
{
    public static void main(String[] args)
    {
        // Points earned on the quiz, out of 20.
        int quizScore = 18;
        // Extra credit for showing all work.
        int bonus = 2;
        // The bonus may push the score above 20. That is allowed.
        quizScore += bonus;
        System.out.print("Final quiz score: ");
        System.out.println(quizScore);
    }
}
Final quiz score: 20

Step by step, here is what the compiler and the computer do with the second version:

  1. The compiler reaches line 5, sees //, and skips the rest of the line. The same happens on lines 7 and 9.
  2. What is left to translate is exactly the five statements from the first program.
  3. When the program runs, it stores 18 in quizScore, stores 2 in bonus, adds the bonus (quizScore becomes 20), and prints the label and the score.

The output is identical. The only difference is for the human reader: the comments answer all three questions (18 is the quiz score out of 20, 2 is extra credit, and going above 20 is allowed).

Now change one thing: put a Java statement inside a comment. Programmers do this on purpose to switch a line off without deleting it, which is called commenting out the line.

int tickets = 3;
// System.out.println("Checking tickets...");
tickets *= 2;
System.out.println(tickets);
6

Line 2 is a perfectly good println statement, but it sits after //, so the compiler treats it as a note and the program never prints Checking tickets.... Only line 4 prints, showing tickets after it was doubled. The rule depends on where the text is, not on what the text looks like: anything inside a comment is ignored, even if it is valid Java.

Watch out

Trusting a comment over the code. Because the compiler never reads comments, it cannot tell you when a comment is wrong. Read this carefully:

int score = 80;
// Add 10 bonus points.
score += 5;
System.out.println(score);
85

A student who reads only the comment predicts 90. But the comment is out of date: someone changed the bonus to 5 and forgot to update the note. The program does what the code says, so it prints 85. When a comment and the code disagree, the code wins. Whenever you change code, update its comment in the same moment, or you leave a trap for the next reader.

Pause and try

Question 1 · Multiple choice

A programmer adds ten comments to a program that already compiles and prints 42. Nothing else changes. What happens?

  1. The program still prints 42, because the compiler ignores comments.
  2. The program prints the comments along with 42.
  3. The program runs more slowly, because the computer has to read each comment.
  4. The program no longer compiles, because comments are not Java statements.
Check your reasoning

A. Comments are skipped by the compiler, so the translated program is exactly the same as before, and it prints 42.

  • B is wrong: only print and println statements produce output. A comment is never executed, so it is never displayed.
  • C is wrong: comments are not translated, so the running program does not contain them and cannot spend time on them.
  • D is wrong: comments are allowed anywhere their markers are written correctly. They are not statements, so the compiler does not check them as Java.

Reread 1.8.1 Comments Are Notes for People if you chose differently.

Question 2 · Tracing

What does this code print?

int laps = 4;
// laps += 3;
laps *= 2;
// System.out.println(laps);
laps -= 1;
System.out.println(laps);
Check your reasoning
7
Line What happens laps
1 laps is set to 4 4
2 Comment: skipped 4
3 laps *= 2 doubles it 8
4 Comment: skipped, nothing shown 8
5 laps -= 1 subtracts 1 7
6 Prints laps 7

Lines 2 and 4 contain valid Java, but they are commented out, so they never run. If you got 13 or printed 8 as well, you ran a commented-out line. Reread 1.8.1 Comments Are Notes for People.

Section 2 of 6

1.8.2 Single-Line Comments

Most notes a programmer needs are short: what a variable stands for, the units of a number, why a step is there. For those, a whole paragraph is too much. You want a note that fits on one line, sometimes on the same line as the code it explains.

A single-line comment starts with // and ends at the end of that line. It can take up a whole line by itself, or it can come after code on the same line, which is called an end-of-line comment.

// A whole-line comment: the entire line is a note.
int count = 3;   // An end-of-line comment: the code runs, the note does not.

Take the second line apart:

  • int count = 3; comes before //, so it is ordinary code. The compiler translates it and it runs.
  • // marks where the comment begins.
  • An end-of-line comment: ... runs to the end of the line and is ignored.

There is no closing marker. The end of the line ends the comment, so the next line is code again.

Worked example: Labeling units with end-of-line comments

Each statement below has a note on its right. Look for where each note begins.

double price = 4.5;   // price of one smoothie, in dollars
int count = 3;        // smoothies ordered
double total = price * count;   // 3 times 4.5
System.out.println(total);
13.5
  1. Line 1: double price = 4.5; runs; the note “price of one smoothie, in dollars” tells the reader the unit.
  2. Line 2: int count = 3; runs; the note says what is being counted.
  3. Line 3: double total = price * count; runs. A double times an int gives a double (Topic 1.3), so total is 13.5. The note 3 times 4.5 is ignored, even though it looks like arithmetic.
  4. Line 4 prints 13.5.

Now vary the order on a line. In int pages = 320; // number of pages, the code comes first and runs. Flip it, and the code is gone:

Watch out

Putting code after // on the same line. A student types the note first and the declaration after it:

CommentSwallowsCode.java
public class CommentSwallowsCode
{
    public static void main(String[] args)
    {
        // number of pages in the book int pages = 320;
        System.out.println(pages);
    }
}

Everything after // on line 5 is a comment, including int pages = 320;. So pages is never declared, and line 6 cannot use it. The compiler reports:

CommentSwallowsCode.java:6: error: cannot find symbol
        System.out.println(pages);
                           ^
  symbol:   variable pages

(The exact wording can vary between Java versions.) The fix is to put the code first and the note after it:

int pages = 320; // number of pages in the book
System.out.println(pages);

This prints 320. A // comment is always the last thing on its line.

Pause and try

Question 3 · Multiple choice

In the line double tip = bill * 0.2; // 20% of bill * 0.2, which part does the compiler translate?

  1. Nothing; a line that contains // is skipped completely.
  2. double tip = bill * 0.2; only
  3. The whole line, including 20% of bill * 0.2
  4. Only 20% of bill * 0.2, because it comes last
Check your reasoning

B. A single-line comment starts at // and runs to the end of the line. Code before // is ordinary code.

  • A is wrong: only the part from // onward is ignored. End-of-line comments rely on the code before them still running.
  • C is wrong: the text after // is a note, even though it looks like math.
  • D is wrong: it reverses the rule. What comes after // is the part that is ignored.

Reread 1.8.2 Single-Line Comments if you chose differently.

Question 4 · Debugging

This code is supposed to start an album with 12 stamps, add 6, and print 18. It compiles, but it prints 12. Find the error and correct it.

int stamps = 12; // stamps in the album stamps += 6;
System.out.println(stamps);
Check your reasoning

The error: stamps += 6; is on line 1, after //. That makes it part of the comment “stamps in the album stamps += 6;”, so it never runs. stamps stays 12.

Corrected code:

int stamps = 12; // stamps in the album
stamps += 6;
System.out.println(stamps);

Now stamps += 6; is on its own line, outside any comment, and the code prints 18.

Notice that the original compiles. Unlike the pages example in 1.8.2, nothing later depends on a missing declaration, so the compiler has nothing to complain about. The result is a logic error (Topic 1.1): the program runs to the end with the wrong answer. Reread 1.8.2 Single-Line Comments if you did not spot it.

Section 3 of 6

1.8.3 Block Comments

Sometimes a note needs several lines: a description of what a whole program does, or a few sentences about how a tricky step works. You could start every line with //, but there is a tool made for longer notes.

A block comment starts with /* and ends with */. Everything between the two markers is a comment, no matter how many lines it covers. Unlike //, the end of a line does not end a block comment; only */ does.

Worked example: Describing a program with a block comment

Lines 1 through 5 are one block comment. Look for where it opens and closes.

GardenOrder.java
/*
 * GardenOrder
 * Works out how many seed packets to buy for a garden.
 * Each row of the garden needs 4 packets.
 */
public class GardenOrder
{
    public static void main(String[] args)
    {
        int rows = 6;
        int packets = rows * 4;
        System.out.println(packets);
    }
}
24
  1. Line 1 opens the comment with /*. From here on, the compiler ignores everything.
  2. Lines 2 to 4 are the note. The * at the start of each line is only decoration that many programmers use to make the block easy to see. It is ignored like the rest.
  3. Line 5 closes the comment with */. Line 6 is code again.
  4. The program runs: rows is 6, packets is 6 × 4 = 24, and line 12 prints 24.

Now use a block comment for a different job: switching off several lines at once.

int rows = 6;
/*
rows += 2;
System.out.println("Added two rows");
*/
int packets = rows * 4;
System.out.println(packets);
24

Lines 3 and 4 are valid statements, but they sit between /* on line 2 and */ on line 5. Neither runs: rows stays 6 (not 8), Added two rows is never printed, and the output is still 24. Commenting out four lines with // would take four markers; a block comment takes one pair.

Watch out

Forgetting the closing */. Since only */ ends a block comment, leaving it out turns the rest of the file into a comment:

UnclosedComment.java
public class UnclosedComment
{
    /*
     * Prints a reminder before the test.

    public static void main(String[] args)
    {
        System.out.println("Bring a calculator!");
    }
}

The comment opened on line 3 never closes, so the compiler swallows main, the println, and both closing braces. It reports:

UnclosedComment.java:3: error: unclosed comment
    /*
    ^

usually followed by a second error saying the end of the file was reached too early (wording can vary between Java versions). Fix it by adding */ on its own line after the note, before public static void main. Whenever you type /*, type */ right away and then fill in the note between them.

Here are the two kinds of comments so far, side by side:

Kind Starts with Ends at Typical use
Single-line comment // The end of that line Short note on one line, or after code
Block comment /* The next */ Notes several lines long; switching off a block

Pause and try

Question 5 · Tracing

What does this code print? Watch where the block comment ends.

int coins = 10;
/* coins += 5;
coins *= 2; */ coins -= 3;
System.out.println(coins);
Check your reasoning
7
Line What happens coins
1 coins is set to 10 10
2 /* opens a block comment; coins += 5; is inside it 10
3 coins *= 2; is still inside; */ closes the comment; coins -= 3; is code 7
4 Prints coins 7

A block comment ends exactly at */, even in the middle of a line, so the code after it on line 3 runs. If you got 10, you treated all of line 3 as a comment. If you got 27, you ran the commented-out lines. Reread 1.8.3 Block Comments.

Question 6 · Multiple choice

A program has /* on line 4 and no */ anywhere after it. What happens?

  1. Only line 4 is a comment; the rest of the program compiles normally.
  2. The program compiles, but nothing after line 4 runs.
  3. The program does not compile, because the comment never ends.
  4. Java closes the comment automatically at the end of line 4.
Check your reasoning

C. Only */ ends a block comment, so everything after line 4 becomes part of it. The compiler reaches the end of the file still inside a comment and reports an “unclosed comment” error. A program with that error cannot run.

  • A and D are wrong: they treat /* like //. The end of a line does not end a block comment.
  • B is wrong: a program with a compile error is never translated, so nothing runs at all (Topic 1.1).

Reread 1.8.3 Block Comments if you chose differently.

Section 4 of 6

1.8.4 Javadoc Comments and API Documentation

In Topic 1.7 you learned that a library’s documentation tells you what its classes can do: the methods of String and Math, what each one needs, and what each one gives back. Someone had to write those pages. Writing them separately from the code would be risky, since the pages and the code could drift apart. So the people who write a class put the documentation inside the source code, right above each class and method, and a tool builds the pages from it.

A Javadoc comment starts with /** (a slash and two stars) and ends with */. It is written directly above a class or a method and describes it. To the compiler, a Javadoc comment is just another comment and is ignored. But a separate tool that comes with Java, called javadoc, reads every /** */ comment in a class and turns them into the documentation pages, known as the API documentation, that programmers read. The String documentation you looked at in Topic 1.7 was built this way from comments in the String class’s source code.

Key idea

A Javadoc comment, written /** */ directly above a class or method, is ignored by the compiler like any comment, and is used by the javadoc tool to create API documentation.

Worked example: Inside the String class

Here is a simplified sketch of how the String class’s source code begins. The real file is far longer, and its comments use different wording; this keeps only the shape. The bodies are left out, so this is for reading, not running.

/**
 * A String holds a sequence of characters, such as "Hopper".
 */
public class String
{
    /**
     * Returns the number of characters in this string.
     *
     * @return the number of characters in this string
     */
    public int length()
    {
        // ...the statements that count the characters...
    }
}

Read it from the top:

  1. The first comment, opened by /**, sits directly above public class String. It describes the whole class. The javadoc tool puts this sentence at the top of the String documentation page.
  2. The second Javadoc comment sits directly above the method header public int length(). Its first sentence becomes the method’s description on the page. (public is a word you can read past for now; method headers are taught fully in Topic 1.9.)
  3. The line beginning with @return holds a Javadoc tag. A tag is a word starting with @ that the javadoc tool treats specially. @return describes the value the method gives back, and the tool lists it under a “Returns” heading.
  4. Inside the method’s braces is an ordinary // comment. It is a note for whoever maintains String, not for users of the class, so the tool does not put it on the documentation page.

A second common tag is @param, which describes a value the method needs to be given. Here is a simplified Javadoc comment for a Math method you will use in Topic 1.11:

/**
 * Returns the absolute value of a: the value without its minus sign.
 *
 * @param a  the number to use
 * @return   the absolute value of a
 */
public static int abs(int a)

The @param line names a, the value that goes in, and says what it is. The @return line says what comes out. (public static can be read past for now; those words are explained in later topics.)

Javadoc comments work in your own programs too. This program has one above the class and one above main:

TipCalculator.java
/**
 * Works out the tip on a restaurant bill.
 */
public class TipCalculator
{
    /**
     * Prints a 20 percent tip on a 45-dollar bill.
     */
    public static void main(String[] args)
    {
        double bill = 45.0;
        double tip = bill * 0.2;
        System.out.println(tip);
    }
}
9.0

The compiler skips lines 1 to 3 and 6 to 8, just as it skips any comment. The program stores 45.0 in bill, computes 45.0 × 0.2 = 9.0, and prints 9.0. The Javadoc comments change nothing about how the program runs; they only give the javadoc tool something to turn into documentation.

Watch out

Writing /* when you mean /**. A comment that starts with /_and one that starts with/**look almost the same, and both compile, because the compiler ignores both. The difference shows up only in the documentation: the javadoc tool collects comments that start with/**and skips ordinary block comments. A student who writes a careful description in/_ _/above a method will find it missing from the documentation pages. Use/\*\*for documentation that users of a class should see, and/_or// for notes about how the code works inside.

All three kinds of comments together:

Kind Written as Ignored by the compiler? Used for
Single-line // … Yes A short note to the end of the line
Block /* … */ Yes A note spanning several lines
Javadoc /** … */ Yes Describing a class or method; builds API documentation

Pause and try

Question 7 · Multiple choice

A programmer wants the description of a method to appear in the API documentation for her class. Which comment should she write directly above the method header?

  1. // Returns the total price in cents.
  2. /* Returns the total price in cents. */
  3. /** Returns the total price in cents. */
  4. Any of these; the javadoc tool reads every comment.
Check your reasoning

C. The javadoc tool builds API documentation from comments that start with /** and sit directly above a class or method.

  • A is wrong: a // comment is a note for people reading the code. It is not collected into the documentation.
  • B is wrong: this is an ordinary block comment, one star short of a Javadoc comment, so the tool skips it.
  • D is wrong: only /** */ comments become documentation. All three are ignored by the compiler, but that is a different question.

Reread 1.8.4 Javadoc Comments and API Documentation if you chose differently.

Question 8 · Short answer

Here is a simplified Javadoc comment from the Math class. Using only the comment, say what you must give this method, and what it gives back.

/**
 * Returns the larger of two values.
 *
 * @param a  one number
 * @param b  another number
 * @return   the larger of a and b
 */
public static int max(int a, int b)
Check your reasoning

Model answer: The two @param lines say I must give the method two numbers, a and b. The @return line says it gives back whichever of the two is larger. For example, given 7 and 12, it gives back 12.

A complete answer must:

  • use the @param lines to name what goes in (two values), and
  • use the @return line (or the first sentence) to name what comes out (the larger one).

Reread 1.8.4 Javadoc Comments and API Documentation if your answer differed.

Section 5 of 6

1.8.5 Preconditions

A recipe for bread might say, “Start with the oven heated to 200 °C.” The recipe does not tell you to check the oven; it assumes you already did. If you skip that, the recipe still runs its steps, and you get a pale, raw loaf. Code works the same way: much of it only works if something is already true before it starts.

You have already met a piece of code like that. In Topic 1.5 you rounded a double to the nearest whole number with (int) (x + 0.5), and that trick works only when x is not negative. That “only when” is the idea of this subsection.

A precondition is a condition that has to be true right before a method or a segment of code runs, so that it does what its documentation says. Preconditions are usually stated in a comment. Here is the most important rule about them: the method or code is not expected to check its own precondition. Making sure the precondition is true is the job of whoever uses the code. If the precondition is false, all bets are off: the code may give a wrong answer, or the program may crash.

Key idea

A precondition is what must be true before a method or code segment runs. The code does not check it for you; you are responsible for making it true before you use the code.

Worked example: A precondition that is met, and one that is broken

The comment on line 1 states the precondition for the rounding code.

// Precondition: temperature is not negative.
double temperature = 2.7;
int rounded = (int) (temperature + 0.5);
System.out.println(rounded);
3

With temperature 2.7, the precondition holds (2.7 is not negative). Line 3 adds 0.5 to get 3.2, and the (int) cast drops the decimal part, giving 3. The nearest whole number to 2.7 is 3, so the code worked.

Now change only the value, so the precondition is broken:

// Precondition: temperature is not negative.
double temperature = -2.7;
int rounded = (int) (temperature + 0.5);
System.out.println(rounded);
-2
Step Value
temperature -2.7
temperature + 0.5 -2.2
(int) drops the decimal -2
Correct nearest whole number -3

The code did not stop, warn, or check anything. It ran every step and printed -2, which is wrong: -2.7 is closer to -3. Casting drops the decimal part, which moves a positive number down but a negative number up, so the + 0.5 trick only works on the nonnegative side. The comment warned about exactly this, and it was the user’s job to obey it.

Breaking a precondition does not always give a quiet wrong answer. Sometimes the program crashes. This segment finds a player’s average points per game:

// Precondition: games is greater than 0.
int totalPoints = 84;
int games = 6;
System.out.println("Computing average...");
int average = totalPoints / games;
System.out.println(average);
Computing average...
14

84 / 6 is 14, so all is well. Now suppose the player has not played yet, so games is 0:

// Precondition: games is greater than 0.
int totalPoints = 84;
int games = 0;
System.out.println("Computing average...");
int average = totalPoints / games;
System.out.println(average);
Computing average...
Exception in thread "main" java.lang.ArithmeticException: / by zero

The first println runs, then line 5 asks Java to divide by zero. As you saw in Topic 1.1, that throws an exception and stops the program, so the average is never printed. (The full message also names the line, and its wording can vary between Java versions.) Again, the code did nothing to protect itself; the precondition comment was the only warning.

Methods in Java’s libraries have preconditions too, written in their Javadoc comments. Here is a simplified version of the documentation for the Math class’s square-root method, which you will use in Topics 1.10 and 1.11:

/**
 * Returns the square root of a.
 * Precondition: a is not negative.
 */
public static double sqrt(double a)

No real number times itself is negative, so a negative number has no square root to give back. The method does not promise to check its precondition for you; if you pass a negative number, you do not get a usable answer. So before you call it, you make sure the argument is not negative. Here it is used correctly. (Math.sqrt(area) calls the method on the value of area; Topic 1.10 explains calls like this fully.)

double area = 49.0;
double side = Math.sqrt(area);
System.out.println(side);
7.0

area is 49.0, which is not negative, so the precondition holds and sqrt gives back 7.0.

Watch out

“If the input were bad, the code would tell me.” Students often assume code checks its own inputs and complains about bad ones. A precondition means the opposite: the code assumes the condition is true and goes ahead. The rounding example printed -2 with no warning at all. Before you run code that has a precondition, look at the values you are about to give it and confirm they meet the precondition yourself.

Pause and try

Question 9 · Multiple choice

The documentation for a method says, “Precondition: count is greater than 0.” A program calls the method with count equal to 0. Which statement is true?

  1. The method will notice that count is 0 and print a warning.
  2. The program will not compile, because the precondition is false.
  3. The method may give a wrong result or crash; the caller was responsible for making count greater than 0.
  4. The method will change count to 1 so that its precondition is true.
Check your reasoning

C. A method is not expected to check its precondition. Meeting it is the caller’s job, and if it is not met, the method’s behavior is not guaranteed.

  • A is wrong: nothing promises a check. That is exactly what a precondition does not mean.
  • B is wrong: the compiler ignores comments, so it never reads the precondition. And it cannot know what values a variable will hold when the program runs.
  • D is wrong: the method does not repair its inputs. It simply assumes the condition is true.

Reread 1.8.5 Preconditions if you chose differently.

Question 10 · Tracing

What does this code print? Is that the nearest whole number to temperature?

// Precondition: temperature is not negative.
double temperature = -4.6;
int rounded = (int) (temperature + 0.5);
System.out.println(rounded);
Check your reasoning
-4
Step Value
temperature -4.6
temperature + 0.5 -4.1
(int) drops the decimal -4

It is not the nearest whole number: -4.6 is closer to -5. The value is negative, so the precondition on line 1 is broken, and the rounding trick is not guaranteed to work. The code does not check; it just prints a wrong answer. Reread 1.8.5 Preconditions if your answer differed.

Section 6 of 6

1.8.6 Postconditions

A precondition tells you what you must do before using some code. The other half of the deal is what the code promises after. When you use Math.sqrt correctly, what exactly do you get? If a method changes something, what will be different when it finishes? Without that promise, you would have to read the method’s code to find out, which is what documentation is meant to save you from.

A postcondition is a condition that is always true after a method or code segment finishes running (as long as its precondition was met). A postcondition describes the result: what value the method gives back, or what the current values of an object’s attributes are afterward. Think of it as the method’s promise. The precondition is your side of the deal; the postcondition is the method’s side.

Key idea

A postcondition is the guaranteed outcome after a method or code segment runs: the value it gives back, or the state its object’s attributes are left in.

Worked example: Checking a postcondition on real output

The comments on lines 1 to 3 state both conditions for this segment. Read the postcondition, then check the output against it.

// Precondition: totalMinutes is not negative.
// Postcondition: hours holds the whole hours in totalMinutes,
// and minutes holds the leftover minutes, from 0 to 59.
int totalMinutes = 135;
int hours = totalMinutes / 60;
int minutes = totalMinutes % 60;
System.out.print(hours);
System.out.print(" h ");
System.out.print(minutes);
System.out.println(" min");
2 h 15 min
Line What happens Value
4 totalMinutes is set 135
5 135 / 60, an int division hours is 2
6 135 % 60, the remainder minutes is 15
7–10 Prints the parts on one line 2 h 15 min

The precondition held (135 is not negative), and the postcondition is true afterward: 2 whole hours, and 15 leftover minutes, which is between 0 and 59.

Now vary the input to test the edge of the promise: use 59 minutes, which is less than one hour. Changing line 4 to int totalMinutes = 59; prints:

0 h 59 min

59 / 60 is 0 and 59 % 60 is 59. The postcondition still holds: 0 whole hours, and 59 leftover minutes, which is in the 0 to 59 range. A good postcondition holds for every input that meets the precondition, not just typical ones.

Postconditions appear in Javadoc comments too. In the String sketch from 1.8.4, the line “Returns the number of characters in this string” is a postcondition stated in terms of what is returned: after length runs, you are guaranteed a count of the characters. The sqrt method’s documentation promises that it returns the square root of a.

A postcondition can also describe an object’s attributes (from Topic 1.7, the data a class keeps in variables). Here is the documentation for a method in an invented BankAccount class, whose attribute is the account’s balance. The rest of the header is taught in Topic 1.9; for now, focus on the comment.

/**
 * Adds money to this account.
 * Precondition: amount is greater than 0.
 * Postcondition: the balance has gone up by amount.
 */
public void deposit(double amount)

This method does not give back a value. Its promise is about the attribute: when it finishes, the balance is larger by exactly amount.

Question Precondition Postcondition
When is it true? Right before the code runs Right after the code finishes
Whose job is it? The caller’s: make it true The method’s: it promises this
sqrt example a is not negative Returns the square root of a
deposit example amount is greater than 0 The balance has gone up by amount

Watch out

Mixing up the two. A student writes “Postcondition: amount must be greater than 0.” But that is a requirement on the value given to the method before it runs, so it is a precondition. Ask two questions about any condition: When is it true, before or after? And who makes it true, the caller or the method? A requirement the caller must meet beforehand is a precondition. A result the method guarantees afterward is a postcondition.

Pause and try

Question 11 · Multiple choice

A method that converts a test score to a letter grade is documented with four statements. Which one is a postcondition?

  1. The score must be between 0 and 100.
  2. The score given to the method is an int.
  3. The method returns one of the letters A, B, C, D, or F.
  4. The caller must not pass a negative score.
Check your reasoning

C. It describes the outcome: what the method gives back after it runs.

  • A is wrong: it is a requirement on the input before the method runs, so it is a precondition.
  • B is wrong: it is also about what goes in, not about the result.
  • D is wrong: “the caller must” is the language of a precondition. It is the caller’s job, beforehand.

Reread 1.8.6 Postconditions if you chose differently.

Question 12 · Tracing

The segment from 1.8.6 is run with a new value. What does it print, and is its postcondition true afterward?

// Precondition: totalMinutes is not negative.
// Postcondition: hours holds the whole hours in totalMinutes,
// and minutes holds the leftover minutes, from 0 to 59.
int totalMinutes = 200;
int hours = totalMinutes / 60;
int minutes = totalMinutes % 60;
System.out.print(hours);
System.out.print(" h ");
System.out.print(minutes);
System.out.println(" min");
Check your reasoning
3 h 20 min
Line What happens Value
4 Set the total 200
5 200 / 60 hours is 3
6 200 % 60 minutes is 20

3 × 60 = 180, and 200 − 180 = 20. The precondition held (200 is not negative), so the postcondition is true: 3 whole hours and 20 leftover minutes, which is between 0 and 59. Reread 1.8.6 Postconditions if your answer differed.

Wrap-up · 1 of 5

Putting it together

This complete program uses all three kinds of comments and documents a precondition and a postcondition. Before reading the walkthrough, find each comment and decide which kind it is.

PizzaShare.java
/**
 * Splits pizza slices evenly among friends.
 */
public class PizzaShare
{
    /**
     * Prints each friend's share and the slices left over.
     */
    public static void main(String[] args)
    {
        /*
         * Precondition: friends is greater than 0.
         * Postcondition: each friend's share and the leftover
         * slices have been printed, and leftover is less than friends.
         */
        int slices = 16;   // 2 pizzas, 8 slices each
        int friends = 5;

        int perFriend = slices / friends;   // whole slices only
        int leftover = slices % friends;

        System.out.print("Each friend gets ");
        System.out.println(perFriend);
        // System.out.println("Enjoy!");
        System.out.print("Slices left over: ");
        System.out.println(leftover);
    }
}
Each friend gets 3
Slices left over: 1

The comments.

Lines Kind What it is for
1–3 Javadoc Describes the class; would appear in documentation
6–8 Javadoc Describes main
11–15 Block States the precondition and postcondition for the code below it
16, 19 End-of-line Explain where 16 comes from and that division keeps whole slices
24 Single-line A println that has been commented out

The run. The compiler skips every comment, leaving the statements on lines 16, 17, 19, 20, 22, 23, 25, and 26.

Line What happens Variables or output
16 slices is set slices = 16
17 friends is set friends = 5
19 16 / 5, an int division perFriend = 3
20 16 % 5, the remainder leftover = 1
22–23 Label, then the value Each friend gets 3
24 Commented out: nothing happens
25–26 Label, then the value Slices left over: 1

Checking the conditions. The precondition held, since 5 is greater than 0. So the postcondition must be true, and it is: both values were printed, and the leftover (1) is less than the number of friends (5). If there were 5 or more slices left over, everyone could have had one more, so the division would have been wrong.

Breaking the precondition. If line 17 were int friends = 0;, the precondition would be false. Nothing in the program checks for that. Line 19 would divide by zero, Java would throw an ArithmeticException, and the program would stop before printing anything. The precondition comment is what tells the next programmer to make sure friends is never 0.

Wrap-up · 2 of 5

Vocabulary

Term Definition Example
comment Text in a program written for people to read; ignored by the compiler and never run // points out of 20
commenting out Turning code into a comment so it does not run, without deleting it // tickets += 1;
single-line comment A comment from // to the end of that line int count = 3; // smoothies
block comment A comment from /* to the next */, over any number of lines /* Each row needs 4 packets. */
Javadoc comment A comment from /** to */ placed above a class or method; used to build API documentation /** Returns the number of characters. */
javadoc The tool that turns Javadoc comments into API documentation pages Builds the String documentation
tag A word starting with @ in a Javadoc comment; @param describes an input, @return the result @return the larger of a and b
precondition What must be true right before a method or code segment runs; the caller must make it true, and the code does not check it a is not negative, for sqrt
postcondition What is always true right after a method or code segment runs: what it returns, or the state of its object’s attributes The balance has gone up by amount
Wrap-up · 3 of 5

Chapter summary

  • Comments are notes written for the original programmer and for other programmers. The compiler ignores them and they never run, so they never change a program’s output; code inside a comment (commented out) does not run either.
  • // makes a comment that ends at the end of its line. /* */ makes a block comment that can cover many lines and ends only at */.
  • /** */ makes a Javadoc comment. Written above a class or method, it describes it, and the javadoc tool turns these comments into API documentation like the pages for String and Math. Tags such as @param and @return describe what goes in and what comes out.
  • A precondition is what must be true before a method or code segment runs. The code does not check it; the user is responsible, and breaking it can cause a wrong result or a crash.
  • A postcondition is what is guaranteed to be true afterward, described in terms of the value returned or the values of the object’s attributes.
Wrap-up · 4 of 5

Review questions

Question 13 · Multiple choice

Which statement is true about all three kinds of Java comments (//, /* */, and /** */)?

  1. They are all used by the javadoc tool to create API documentation.
  2. They are all ignored by the compiler and never executed.
  3. They all end at the end of the line on which they start.
  4. They are all printed when the program runs, so users can read them.
Check your reasoning

B. Every kind of comment is skipped by the compiler, so none of them run.

  • A is wrong: only /** */ comments become API documentation.
  • C is wrong: only // ends at the end of its line. /* */ and /** */ end at */, which may be many lines later.
  • D is wrong: comments are for people reading the code, not for people running the program. Only print statements produce output.

Reread 1.8.1 Comments Are Notes for People and the table in 1.8.4 Javadoc Comments and API Documentation if you chose differently.

Question 14 · Tracing

What is the exact output of this program?

ReadingLog.java
/**
 * Keeps count of the books a student has read.
 */
public class ReadingLog
{
    public static void main(String[] args)
    {
        int books = 2; // read in September
        /* books += 4;  read in October
           books += 1; */
        books *= 3; // books -= 1;
        // books += 10;
        System.out.print("Books: ");
        System.out.println(books);
    }
}
Check your reasoning
Books: 6
Line What happens books
1–3 Javadoc comment: skipped
8 books is set to 2; the note after // is skipped 2
9–10 A block comment from /* to */: both += lines are skipped 2
11 books *= 3 runs; // books -= 1; is an end-of-line comment 6
12 Commented out 6
13–14 Prints the label, then the value 6

If you got Books: 21, Books: 5, or a total including the 10, you ran one of the commented-out lines. Reread 1.8.2 Single-Line Comments and 1.8.3 Block Comments.

Question 15 · Debugging

This code should record 5 cups of water, then add 3 glasses of 2 cups each, and print 11. It prints 5. Find the error and correct it.

int water = 5; // cups of water so far
/* Each glass holds 2 cups.
   The student drinks 3 more glasses.
water += 2 * 3; */
System.out.println(water);
Check your reasoning

The error: the block comment opens on line 2 but does not close until the end of line 4, so water += 2 * 3; is inside the comment and never runs.

Corrected code:

int water = 5; // cups of water so far
/* Each glass holds 2 cups.
   The student drinks 3 more glasses. */
water += 2 * 3;
System.out.println(water);

Moving */ to the end of the note lets water += 2 * 3; run: 2 × 3 is 6, and 5 + 6 is 11, so the code prints 11. The original compiled because the comment did close eventually; it just closed one line too late, which is a logic error. Reread 1.8.3 Block Comments if you did not spot it.

Question 16 · Short answer

A library includes this documentation for a method in an invented Ticket class:

/**
 * Works out the total cost of an order of tickets.
 * Precondition: quantity is greater than 0, and priceCents is not negative.
 * Postcondition: returns quantity times priceCents.
 */
public static int totalCost(int quantity, int priceCents)

(a) Who is responsible for making sure quantity is greater than 0? (b) If a program passes 0 for quantity, what does the documentation promise about the result? (c) Which kind of comment is this, and how can you tell?

Check your reasoning

Model answer: (a) The programmer who calls totalCost is responsible. The method is not expected to check its precondition. (b) Nothing. The postcondition is only guaranteed when the precondition was met, so with quantity 0 the documentation makes no promise about what comes back. (c) It is a Javadoc comment, because it starts with /** and sits directly above a method header, so the javadoc tool would put it in the API documentation.

A complete answer must:

  • give the job of meeting the precondition to the caller, not the method,
  • say that breaking the precondition means the postcondition is no longer promised, and
  • identify the comment as Javadoc from its /** opening.

Reread 1.8.5 Preconditions, 1.8.6 Postconditions, and 1.8.4 Javadoc Comments and API Documentation if your answer differed.

Question 17 · Tracing

The minutes segment from 1.8.6 is run with a value that breaks its precondition. What does it print, and which part of the postcondition is false afterward?

// Precondition: totalMinutes is not negative.
// Postcondition: hours holds the whole hours in totalMinutes,
// and minutes holds the leftover minutes, from 0 to 59.
int totalMinutes = -135;
int hours = totalMinutes / 60;
int minutes = totalMinutes % 60;
System.out.print(hours);
System.out.print(" h ");
System.out.print(minutes);
System.out.println(" min");
Check your reasoning
-2 h -15 min
Line What happens Value
4 Set the total -135
5 -135 / 60 hours is -2
6 -135 % 60 minutes is -15

In Java, an int division of a negative number drops the decimal part, giving -2, and the remainder keeps the sign of the number being divided, giving -15. The postcondition promised leftover minutes from 0 to 59, and -15 is outside that range, so that part is false. That is allowed: the precondition (not negative) was broken, so the postcondition was never promised. The code ran without complaint and printed a strange result. Reread 1.8.5 Preconditions and 1.8.6 Postconditions if your answer differed.

Question 18 · Multiple choice

A programmer writes this segment to split cookies evenly into boxes:

int perBox = cookies / boxes;

Which comment is the best precondition to write above it?

  1. // Precondition: perBox holds the number of cookies in each box.
  2. // Precondition: boxes is not 0.
  3. // Precondition: the code checks that boxes is not 0.
  4. // Precondition: perBox is greater than 0.
Check your reasoning

B. A precondition states what must already be true before the code runs. Dividing by zero throws an exception, so boxes must not be 0 when this line runs.

  • A is wrong: it describes the result after the line runs, so it is a postcondition, not a precondition.
  • C is wrong: the code does no such check. A precondition is a requirement on whoever uses the code, not a promise that the code checks anything.
  • D is wrong: perBox does not have its value until after the line runs, so it cannot be a condition before it. (It could also be 0 with no problem, if there are fewer cookies than boxes.)

Reread 1.8.5 Preconditions and 1.8.6 Postconditions if you chose differently.

Wrap-up · 5 of 5

Reflection

Check each statement. If the answer is “not yet,” reread the linked subsection.

  • I can explain who comments are for and why they never change what a program prints. Reread
  • I can tell which part of a line is code and which part is a // comment. Reread
  • I can find where a /* */ block comment starts and ends, even in the middle of a line. Reread
  • I can explain how /** */ comments become API documentation and read @param and @return. Reread
  • I can state a precondition and explain that the caller, not the code, must make it true. Reread
  • I can state a postcondition and tell it apart from a precondition. Reread