Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Java  Module 2 – Variables, types and operators

Comments, Javadoc and naming conventions

Write line, block and Javadoc comments, including /// Markdown doc comments, generate HTML with javadoc, and name classes, methods and constants the Java way.

  • Beginner
  • 15 minutes
  • Examples run with Java 25.0.4 and Python 3.14.8
  • By MySmartCoPilot
Free lesson, Pro answers: 15 minutes
Free: the whole lesson. With a pass: the model answers to its 2 interview questions.

What you will learn

  • Write line, block and documentation comments, and predict where a comment ends
  • Recognise a Unicode escape that ends a comment early
  • Document a class and its methods with /// and /** */ comments and their block tags
  • Generate HTML documentation with javadoc and make doclint fail a build on missing comments
  • Name packages, classes, methods, variables and constants by Java conventions, and use final for values that never change

Before you start

What you’ll learn · Before you start

What you will learn

  • Write line, block and documentation comments, and predict where a comment ends
  • Recognise a Unicode escape that ends a comment early
  • Document a class and its methods with /// and /** */ comments and their block tags
  • Generate HTML documentation with javadoc and make doclint fail a build on missing comments
  • Name packages, classes, methods, variables and constants by Java conventions, and use final for values that never change

Before you start

On this page

One line in this lesson looks like a comment and still changes a discount from 10 % to 50 %, because Java turns the six characters \u000a into a line break before it looks for comments at all. Comments are what the compiler skips and names are what a reader reads first, so both decide whether code says what it does. Java has three kinds of comments: // to the end of the line, /* … */ blocks, and documentation comments, which the javadoc tool turns into HTML pages.

You will step through how the compiler reads a block comment that seems to nest, document one class in both the HTML and the Markdown style, let doclint report what is missing, and name things the way the Java Language Specification recommends. A rule of thumb runs through all of it: let names say what the code does, and let comments say why.

Three kinds of comments, and block comments do not nest

An end-of-line comment starts with // and runs to the end of the line. A block comment runs from /* to the next */. A documentation comment: A comment directly above a class, field, constructor or method that the javadoc tool turns into HTML: /** … */ in HTML with tags, or, from Java 23, consecutive /// lines in Markdown. The compiler ignores it like any comment. describes the class, method or field right below it, written either as /** … */ in HTML or, since Java 23, as lines that start with ///, in Markdown. The compiler ignores all three:

Comments.java Java · Comments.java
// An end-of-line comment: from the two slashes to the end of the line.

/* A block comment can run over
   several lines, and it ends at the first star and slash. */

/// A documentation comment, written in Markdown (Java 23 and later). The javadoc tool turns it into HTML.
void main() {
    int seats = 40;                       // a comment can follow code on the same line
    /* or sit inside a line */ seats = seats + 2;
    IO.println("seats: " + seats);
}
Comments are ignored, and they do not nest Python · comments_session.py
from session import run, version

# Comments.java runs; Nested.java does not even compile, because block comments do not nest.
version()
run("""
java Comments.java
java Nested.java
""", expect_failure=("java Nested.java",))

Output

# openjdk version "25.0.4.1" LTS
$ java Comments.java
seats: 42
$ java Nested.java
Nested.java:6: error: not a statement
    */
     ^
Nested.java:6: error: illegal start of expression
    */
    ^
2 errors
error: compilation failed
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 comments_session.py

  • // comments end at the end of the line, so they can follow code on the same line.
  • /* … */ comments can run over several lines or sit in the middle of one, and they end at the first */.
  • /// … lines are comments to the compiler too. Only javadoc gives them a meaning, as the section on documentation shows.
  • Inside a // comment, /* and */ mean nothing, and inside a block comment // means nothing. Inside a string literal neither starts a comment: "/* not a comment */" is just text.

Block comments do not nest. Nested.java tried to switch off a rule that already held a comment, and the compiler stopped at line 6. Step through how it read lines 3 to 6:

Interactive · step by step How the compiler reads a comment inside a comment Step through lines 3 to 6 of Nested.java. The left column is the source, the right one what the compiler makes of it.
How the compiler reads a comment inside a comment, step 6 of 6. Showing /* The old price rule, a comment starts, /* price = price * 2; */, the first */ ends it, price = price * 3;, read as code, */, error: not a statement. In focus: /* price = price * 2; */, the first */ ends it./* The old price ruleline 3a comment startseverything is text now/* price = price * 2; */line 4the first */ ends itthe inner /* was only textprice = price * 3;line 5read as codea statement, not a comment*/line 6error: not a statementthe compile stops here

The drawing shows the whole scene; its 6 steps are listed below.

Every step as text
  1. A block comment opens. Line 3 starts with /, so a block comment begins. From here on the compiler skips everything until it meets the next /.
  2. The inner opening is only text. Line 4 holds a second /*, but inside a comment it is just two characters. The comment does not count openings.
  3. The first close ends it. The */ at the end of line 4 is the first one the compiler meets, so the comment ends there, although the writer meant it to go on.
  4. Code again. Line 5, price = price * 3;, is now outside any comment, so the compiler reads it as a statement of main.
  5. A stray close. Line 6 holds the / that was meant to close everything. Outside a comment it is a and a /, which make no statement, and the run reported Nested.java:6: error: not a statement.
  6. Switch code off with //. To switch off lines that may hold a block comment, put // in front of each one. A // comment ends at the line break, whatever the line contains.

Switching off code with a block comment

Wrapping lines in /* … */ fails as soon as they hold a block comment of their own: the first */ ends yours, and Nested.java stopped with “not a statement”. Put // in front of each line instead (most editors do that with one key), or simply delete the lines, since version control keeps the old version.

Checkpoint

Check: The three kinds of comments

  1. Question 1 of 2 What does this print?

    Read the code, then choose one answer.

    String s = "/* not a comment */";
    IO.println(s);
    Show the answer: Question 1 of 2

    Answer: /* not a comment */

    Comments are found outside string and character literals only. A literal that looks like a comment is just text.

  2. Question 2 of 2 Where does a comment that starts with // end?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: At the end of its line

    Because a // comment ends at the line break, it can follow code on the same line, as seats = 40; did in Comments.java, and it is the safe way to switch off a line.

A Unicode escape can end a comment early

Before the compiler looks for comments at all, it replaces every Unicode escape: A backslash, the letter u and four hexadecimal digits, such as \u000a, that stands for one character. The compiler replaces every one in a source file before it looks for comments, so \u000a in a comment is a real line break., \u followed by four hexadecimal digits, with the character it stands for. \u000a stands for a line break:

UnicodeTrap.java Java · UnicodeTrap.java
// A comment that runs: a Unicode escape for a line break ends the comment early.
void main() {
    int discount = 10;
    // Festival offer ends tonight \u000a discount = 50;
    IO.println("discount: " + discount + "%");
}
A comment that changed the result Python · trap_session.py
from session import run

# UnicodeTrap.java compiles without a warning, prints 50%, and grep finds the escape that did it.
run("""
javac -Xlint:all -d classes UnicodeTrap.java
java UnicodeTrap.java
grep -n 'u000a' UnicodeTrap.java
""")

Output

$ javac -Xlint:all -d classes UnicodeTrap.java
$ java UnicodeTrap.java
discount: 50%
$ grep -n 'u000a' UnicodeTrap.java
4:    // Festival offer ends tonight \u000a discount = 50;

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 trap_session.py

Step through what the compiler did with line 4:

Interactive · stage by stage A comment that runs Step through what the compiler does with line 4 of UnicodeTrap.java, from the text as typed to the result printed.
A comment that runs, step 5 of 5. Showing Line 4, as typed, The escape is replaced, Two lines now, discount = 50; is code, discount: 50%. In focus: discount: 50%.Line 4, as typeda // comment holding \u000aThe escape is replaced\u000a: a real line breakTwo lines nowthe comment ends at itdiscount = 50; is codea statement of maindiscount: 50%what the program printed

The drawing shows the whole scene; its 5 steps are listed below.

Every step as text
  1. The line as typed. Line 4 starts with //, so it looks like one comment from start to end. The six characters \u000a sit in the middle of it.
  2. Escapes come first. Before the compiler looks for comments at all, it replaces every Unicode escape with the character it stands for. \u000a stands for a line break.
  3. The comment ends early. A // comment runs to the end of its line, and that line now ends where the escape was. Everything after it is on a new line.
  4. A statement appears. discount = 50; is on a line of its own and outside any comment, so it compiles as a statement. javac -Xlint:all printed no warning about it.
  5. The result changes. The program printed discount: 50% although the line that sets 50 looks commented out. A search for u000a, as the grep in the run did, finds such lines.

\u000a became a real line break, the comment ended in the middle of line 4, and discount = 50; became a statement that ran, so the program printed discount: 50%. javac -Xlint:all, with every warning switched on, said nothing. \u000d, a carriage return, ends a comment in the same way.

Writing a Unicode escape in a comment

A comment that holds \u000a or \u000d ends there, and whatever follows on the line is compiled. Write the character itself, or name it in words, as U+000A. When you read code, a search for u000a and u000d, as the grep above did, finds such lines.

Checkpoint

Check: Unicode escapes in comments

  1. One question A method holds int rate = 9;, then the line // old rate \u000d rate = 12;, then IO.println(rate);. What does it print?

    Choose one answer.

    A hint

    \u000d is a carriage return, and a carriage return ends a line.

    Show the answer: One question

    Answer: 12

    \u000d works like the lesson's \u000a: a carriage return is a line terminator, so the // comment ends at it and the rest of the line is ordinary code, so rate becomes 12.

A documentation comment documents the declaration right below it

A documentation comment goes directly above what it describes: a class, an interface, a field, a constructor or a method. The javadoc tool turns these comments into the same kind of HTML pages as the JDK’s own API documentation:

javadoc reads the /// comments in Fees.java, writes HTML pages into docs, and reports missing comments and tags as warnings.Fees.java, with ///comments above the classand each public methodjavadoc -Xdoclint:all-d docs Fees.javadocs/Fees.html: summary,parameters, returns, throwsWarnings: no comment,no @param, no @returnreadswriteschecks

What javadoc does with documentation comments

Text description of the diagram

The diagram shows the javadoc tool between a source file and its output.

  1. Fees.java holds documentation comments: /// lines directly above the class and above each public method.
  2. The command javadoc -Xdoclint:all -d docs Fees.java reads those comments.
  3. It writes HTML pages into the docs folder, among them Fees.html, which shows each method's summary, its parameters, its return value and the exceptions it throws.
  4. It also checks the comments with doclint, every group of checks with -Xdoclint:all, and reports anything missing as a warning: a public class or method without a comment, a parameter without @param, a method without @return.

The same class, documented in both styles:

Fees.java, documented in Markdown and in HTML

/// Markdown · markdown/Fees.java

/// Fee calculations for a coaching institute.
///
/// Every amount is a whole number of paise, so that no rounding error can build up.
public final class Fees {
    private Fees() {}

    /// Returns the fee after a percentage discount.
    ///
    /// The discount is rounded down to a whole paisa, so a student never pays less than the advertised rate. For
    /// example, `discounted(150_000, 10)` returns `135_000`.
    ///
    /// @param fee     the full fee in paise; must not be negative
    /// @param percent the discount, from 0 to 100
    /// @return the fee after the discount, in paise
    /// @throws IllegalArgumentException if `fee` is negative or `percent` is outside 0 to 100
    public static long discounted(long fee, int percent) {
        if (fee < 0 || percent < 0 || percent > 100) {
            throw new IllegalArgumentException("fee " + fee + ", percent " + percent);
        }
        return fee - fee * percent / 100;
    }
}

/** HTML */ · classic/Fees.java

/**
 * Fee calculations for a coaching institute.
 * <p>
 * Every amount is a whole number of paise, so that no rounding error can build up.
 */
public final class Fees {
    private Fees() {}

    /**
     * Returns the fee after a percentage discount.
     * <p>
     * The discount is rounded down to a whole paisa, so a student never pays less than the advertised rate. For
     * example, {@code discounted(150_000, 10)} returns {@code 135_000}.
     *
     * @param fee     the full fee in paise; must not be negative
     * @param percent the discount, from 0 to 100
     * @return the fee after the discount, in paise
     * @throws IllegalArgumentException if {@code fee} is negative or {@code percent} is outside 0 to 100
     */
    public static long discounted(long fee, int percent) {
        if (fee < 0 || percent < 0 || percent > 100) {
            throw new IllegalArgumentException("fee " + fee + ", percent " + percent);
        }
        return fee - fee * percent / 100;
    }
}
javadoc on both versions, and the HTML it wrote for discounted Python · javadoc_session.py
from session import run

# javadoc checks both versions of Fees.java and writes their HTML; sed prints the part about discounted() from the
# Markdown version's page, then grep the description of discounted() from the classic version's page.
run("""
javadoc -quiet -notimestamp -Xdoclint:all -d docs markdown/Fees.java
javadoc -quiet -notimestamp -Xdoclint:all -d docs-classic classic/Fees.java
sed -n '/<section class="detail" id="discounted/,/<[/]section>/p' docs/Fees.html
sed -n '/<section class="detail" id="discounted/,/<[/]section>/p' docs-classic/Fees.html | grep -A3 'class="block"'
""")

Output

$ javadoc -quiet -notimestamp -Xdoclint:all -d docs markdown/Fees.java
$ javadoc -quiet -notimestamp -Xdoclint:all -d docs-classic classic/Fees.java
$ sed -n '/<section class="detail" id="discounted/,/<[/]section>/p' docs/Fees.html
<section class="detail" id="discounted(long,int)">
<h3>discounted</h3>
<div class="horizontal-scroll">
<div class="member-signature"><span class="modifiers">public static</span>&nbsp;<span class="return-type">long</span>&nbsp;<span class="element-name">discounted</span><wbr><span class="parameters">(long&nbsp;fee,
 int&nbsp;percent)</span></div>
<div class="block"><p>Returns the fee after a percentage discount.</p>
<p>The discount is rounded down to a whole paisa, so a student never pays less than the advertised rate. For
example, <code>discounted(150_000, 10)</code> returns <code>135_000</code>.</p>
</div>
<dl class="notes">
<dt>Parameters:</dt>
<dd><code>fee</code> - the full fee in paise; must not be negative</dd>
<dd><code>percent</code> - the discount, from 0 to 100</dd>
<dt>Returns:</dt>
<dd>the fee after the discount, in paise</dd>
<dt>Throws:</dt>
<dd><code><a href="https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/IllegalArgumentException.html" title="class or interface in java.lang" class="external-link">IllegalArgumentException</a></code> - if <code>fee</code> is negative or <code>percent</code> is outside 0 to 100</dd>
</dl>
</div>
</section>
$ sed -n '/<section class="detail" id="discounted/,/<[/]section>/p' docs-classic/Fees.html | grep -A3 'class="block"'
<div class="block">Returns the fee after a percentage discount.
<p>
The discount is rounded down to a whole paisa, so a student never pays less than the advertised rate. For
example, <code>discounted(150_000, 10)</code> returns <code>135_000</code>.</div>

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 javadoc_session.py

How a documentation comment is built:

  • The first sentence is the summary, the one line shown in the list of methods. The sentences after it are the full description.
  • In Markdown a blank /// line starts a new paragraph, and code goes between backticks. The HTML form writes <p> and {@code …} for the same things.
  • block tag: A tag at the end of a documentation comment that starts a section of the page: @param for a parameter, @return for the result and @throws for an exception, each followed by its description. come last: @param for each parameter, @return for the result and @throws for each exception a caller should expect. They became the Parameters, Returns and Throws parts of the page.
  • A link to another class or method is [String] or [String#strip()] in Markdown, and {@link String#strip()} in the HTML form.
  • The /// lines must follow each other without a gap. A blank line, or an ordinary comment, between them splits the comment, and only the last part documents the declaration.

javadoc printed nothing for either version, which means no warnings. The last command printed the description of discounted from the classic version’s page: the same sentences, and the only difference is that the Markdown version puts each paragraph in a <p> of its own. -quiet hides its progress messages, -notimestamp leaves the time stamp out of the pages, so that two runs write the same files, and -d docs names the folder for the pages. The two styles of Fees.java, side by side:

Classic /** … */, in HTML Markdown ///, from Java 23
<p> starts a paragraph a blank /// line starts a paragraph
{@code x} for code `x` for code
{@link String} for a link [String] for a link
@param, @return, @throws the same block tags
read by every javadoc read by javadoc from Java 23 on

Use /// for new code built with Java 23 or later, and keep /** … */ where the documentation must still build with an older JDK.

Version note

Markdown documentation comments arrived in Java 23 with JEP 467, so they work in Java 25. A javadoc from Java 22 or earlier treats /// lines as ordinary end-of-line comments and documents nothing from them.

Markdown Editor Draft a long /// comment in Markdown with a live preview before you paste it above the method.

Checkpoint

Check: Documentation comments and their tags

  1. Question 1 of 2 Which part of a documentation comment becomes the one-line summary in the list of methods?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: Its first sentence

    Start every documentation comment with one sentence that says what the method does or returns, such as Returns the fee after a percentage discount.

  2. Question 2 of 2 Above a method stand two groups of /// lines with a blank line between them. Which text does javadoc use as the method's documentation?

    Choose one answer.

    Show the answer: Question 2 of 2

    Answer: Only the second group, the one right above the method

    The lesson's rule: /// lines must be consecutive. The blank line makes two comments, and only the last comment before the method documents it; the first group documents nothing.

doclint reports the comments and tags that are missing

javadoc runs a checker called doclint: The checker inside javadoc and javac that reports problems in documentation comments, such as a public method with no comment, no @param for a parameter or no @return. -Xdoclint:all turns on every group of checks., switched on by default, which reports problems in documentation comments as warnings. Its checks come in five groups, accessibility, html, missing, reference and syntax. -Xdoclint:all switches every group on, missing included, the one for missing comments and tags, while -Xdoclint:all,-missing would switch on every group but that one. Naming the option keeps a build’s checks from depending on what a JDK’s default happens to be. This class has a comment on its method, but not every part a caller needs:

HalfDone.java Java · HalfDone.java
/// Marks of one student.
public final class HalfDone {
    private HalfDone() {}

    /// Returns the average of the marks.
    public static double average(int[] marks) {
        int total = 0;
        for (int mark : marks) total += mark;
        return (double) total / marks.length;
    }
}
doclint with and without -Werror Python · doclint_session.py
from session import run

run("""
javadoc -quiet -notimestamp -Xdoclint:all -d docs HalfDone.java
javadoc -quiet -notimestamp -Xdoclint:all -Werror -d docs-strict HalfDone.java
""", expect_failure=("javadoc -quiet -notimestamp -Xdoclint:all -Werror -d docs-strict HalfDone.java",))

Output

$ javadoc -quiet -notimestamp -Xdoclint:all -d docs HalfDone.java
HalfDone.java:6: warning: no @param for marks
    public static double average(int[] marks) {
                         ^
HalfDone.java:6: warning: no @return
    public static double average(int[] marks) {
                         ^
2 warnings
$ javadoc -quiet -notimestamp -Xdoclint:all -Werror -d docs-strict HalfDone.java
HalfDone.java:6: warning: no @param for marks
    public static double average(int[] marks) {
                         ^
HalfDone.java:6: warning: no @return
    public static double average(int[] marks) {
                         ^
error: warnings found and -Werror specified
1 error
2 warnings
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 doclint_session.py

The warning What is missing What to add
no comment a public class or method has no documentation comment at all a /// comment above it
no @param for marks a parameter is not described @param marks …
no @return the result is not described @return …

The first run printed both warnings and still ended with exit status 0, so a build that runs it would pass. -Werror turns every warning into an error: the second run printed the same warnings, then error: warnings found and -Werror specified, and failed. That is how a build fails until the documentation is complete. The compiler accepts the same -Xdoclint option, so javac -Xdoclint:all checks documentation while it compiles.

Checkpoint

Check: Checking documentation with doclint

  1. One question A build runs javadoc -Xdoclint:all -d docs HalfDone.java without -Werror, and doclint finds no @return. How does the run end?

    Choose one answer.

    Show the answer: One question

    Answer: It prints the warning and ends with exit status 0, so the build goes on

    -Xdoclint:all decides what is checked and -Werror decides whether a warning fails the run. A build that must keep its documentation complete needs both.

Names follow conventions the compiler does not enforce

The Java Language Specification recommends these conventions, and the JDK’s own classes follow them:

Names of Convention, with examples
Packages all lowercase, usually starting with a reversed domain name: com.example.fees, java.util
Classes, records, enums, interfaces UpperCamelCase nouns, though interfaces may be adjectives: FeeReceipt, ArrayList, Runnable
Methods lowerCamelCase, usually verbs: calculateTotal, isPaid, getAmount, toString
Variables and fields lowerCamelCase nouns: seatsLeft, dueDate, feePerSeat
Constants (static final) UPPER_SNAKE_CASE: MAX_SEATS, EARLY_DISCOUNT_PERCENT
Type variables one capital letter: T, E, K, V

Methods that read a value are named getX, ones that set it setX, ones that answer yes or no isX, and ones that convert toX, as in isEmpty and toString. Good names make the same program readable without comments:

BadNames.java and GoodNames.java

Java (BadNames.java) · BadNames.java

// It works, but no name says what its value means.
void main() {
    int x = 3;
    double y = 4999;
    double z = x * y;
    double t = z - z * 10 / 100;
    IO.println(String.format(Locale.ROOT, "%.2f", t));
}

Java (GoodNames.java) · GoodNames.java

// The same program, with names that say what each value is.
static final int EARLY_DISCOUNT_PERCENT = 10;

void main() {
    int seats = 3;
    double feePerSeat = 4999;
    double fullFee = seats * feePerSeat;
    double feeAfterDiscount = fullFee - fullFee * EARLY_DISCOUNT_PERCENT / 100;
    IO.println(String.format(Locale.ROOT, "%.2f", feeAfterDiscount));
}

Java (Identifiers.java) · Identifiers.java

// Legal names that break the conventions: the compiler accepts them all.
void main() {
    int मूल्य = 499;          // letters of any script are allowed
    int seats_left = 4;       // Java style writes seatsLeft
    int $count = 2;           // the dollar sign is meant for generated code
    IO.println(मूल्य + " " + seats_left + " " + $count);
}
The same result with poor names and with good ones Python · names_session.py
from session import run

# The same calculation with poor names and with good ones, then names that are legal but unusual.
run("""
java BadNames.java
java GoodNames.java
java Identifiers.java
""")

Output

$ java BadNames.java
13497.30
$ java GoodNames.java
13497.30
$ java Identifiers.java
499 4 2

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 names_session.py

Both programs printed 13497.30, but only GoodNames.java tells you that it is a fee for 3 seats after a 10 % discount. The number 10 became the constant EARLY_DISCOUNT_PERCENT, so the next person to change the discount finds it by name instead of guessing which 10 it is.

The conventions are recommendations. The compiler’s rules are looser: a name may use letters and digits of any script, _ and $, must not start with a digit, and must not be a keyword such as class; _ on its own is a keyword too. Identifiers.java compiled a Devanagari name, a snake_case name and a $ name without complaint. Most teams still keep to the conventions and to ASCII letters, so that everyone can read, type and search every name.

Case Converter Turn a phrase into camelCase, PascalCase or CONSTANT_CASE, the tool's name for UPPER_SNAKE_CASE, when you choose a name.

Key idea

The compiler accepts any legal name; the conventions make a name tell its reader what it is: UpperCamelCase for a type, lowerCamelCase for a method or variable, UPPER_SNAKE_CASE for a constant and lowercase for a package.

Checkpoint

Check: Naming conventions

  1. Question 1 of 2 A method answers whether a fee has been paid. Which name follows the Java conventions?

    Choose one answer.

    Show the answer: Question 1 of 2

    Answer: isPaid

    getX reads, setX sets, isX answers yes or no and toX converts, as in isEmpty and toString.

  2. Question 2 of 2 Which of these names compiles as a local variable?
    Show the answer: Question 2 of 2

    Answer: seats$left

    The compiler's rules are looser than the conventions: Identifiers.java compiled a $ name, a snake_case name and a Devanagari one. Most teams still write seatsLeft.

final assigns once, and comments that say why age best

final on a variable means it can be assigned only once, and the compiler enforces it:

FinalCheck.java Java · FinalCheck.java
// final means "assigned once": a second assignment is a compile-time error.
void main() {
    final int maxSeats = 40;
    maxSeats = 45;
    IO.println(maxSeats);
}
A second assignment to a final variable Python · final_session.py
from session import run

# FinalCheck.java assigns a final variable twice, and the compiler refuses it.
run("java FinalCheck.java", expect_failure=("java FinalCheck.java",))

Output

$ java FinalCheck.java
FinalCheck.java:4: error: cannot assign a value to final variable maxSeats
    maxSeats = 45;
    ^
1 error
error: compilation failed
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 final_session.py

A constant is a static final field whose value is fixed in the code, such as static final int MAX_SEATS = 40;, and its UPPER_SNAKE_CASE name tells every reader that it never changes. Marking locals final documents that a value is meant to stay the same, and the compiler checks it for you.

Comments age worse than code, because nothing checks them. Compare two comments on the same kind of line:

A comment that repeats the code A comment that gives the reason
// add 1 to seats above seats = seats + 1; // The organiser's seat is booked with the first student's.
says nothing the line does not say says what no line of code can
is wrong the day someone changes the line stays true while the reason does

In documentation comments, describe what a caller may rely on, such as the units, the allowed values and the exceptions, rather than how the method works inside.

Checkpoint

Check: final, constants and useful comments

  1. One question What happens with this code?

    Read the code, then choose one answer.

    final int maxSeats;
    maxSeats = 40;
    maxSeats = 45;
    Show the answer: One question

    Answer: It does not compile, because of the third line

    final means assigned exactly once, not necessarily on the declaration's line. The error names the variable: cannot assign a value to final variable maxSeats.

Practise: document a utility class

Marks.java is a small class with three public methods and no documentation. Add /// comments to the class and to each public method, with @param for every parameter, @return for every result and @throws for the exception, and run javadoc -quiet -notimestamp -Xdoclint:all -Werror -d docs Marks.java until it prints nothing and finishes with exit status 0.

Marks.java Java · exercise/Marks.java
// Exercise: document this class and its three public methods with /// comments, then run:
//   javadoc -quiet -notimestamp -Xdoclint:all -Werror -d docs Marks.java
// It is done when javadoc prints nothing at all and the exit status is 0.
public final class Marks {
    private Marks() {}

    public static double average(int[] marks) {
        if (marks.length == 0) throw new IllegalArgumentException("no marks");
        int total = 0;
        for (int mark : marks) total += mark;
        return (double) total / marks.length;
    }

    public static int highest(int[] marks) {
        if (marks.length == 0) throw new IllegalArgumentException("no marks");
        int best = marks[0];
        for (int mark : marks) best = Math.max(best, mark);
        return best;
    }

    public static boolean passed(int mark, int passMark) {
        return mark >= passMark;
    }
}

As it starts, javadoc finds four missing comments and stops with an error:

The starting point Python · exercise_session.py
from session import run

# javadoc checks the starter file, which has no documentation comments yet: that is the starting point.
run("javadoc -quiet -notimestamp -Xdoclint:all -Werror -d docs exercise/Marks.java", expect_failure=("javadoc -quiet -notimestamp -Xdoclint:all -Werror -d docs exercise/Marks.java",))

Output

$ javadoc -quiet -notimestamp -Xdoclint:all -Werror -d docs exercise/Marks.java
exercise/Marks.java:4: warning: no comment
public final class Marks {
             ^
exercise/Marks.java:7: warning: no comment
    public static double average(int[] marks) {
                         ^
exercise/Marks.java:14: warning: no comment
    public static int highest(int[] marks) {
                      ^
exercise/Marks.java:21: warning: no comment
    public static boolean passed(int mark, int passMark) {
                          ^
error: warnings found and -Werror specified
1 error
4 warnings
[exit status 1]

Recorded with Python 3.14.8 on macOS 26 arm64. To run it yourself: mise exec python@3.14.8 -- python3 exercise_session.py

A first hint: start each comment with one sentence that says what the method returns, such as /// Returns the average of the marks., then a blank /// line, then the tags. The private constructor needs no comment, because javadoc does not document private members unless you ask it to.

Once javadoc runs clean, the questions below go over the lesson from // to final. A wrong answer is followed by an easier question on the same idea, and every choice tells you what it gets right or misses:

Practice that adapts to you

Practise this lesson

18 questions about 6 ideas of this lesson. Each answer is explained at once, and what you get right is kept in this browser.

  1. Question 1 of 18 Which comment can sit in the middle of a line, with code after it on the same line?

    Choose one answer.

    Show the answer: Question 1 of 18

    Answer: A block comment, /* … */

    A block comment ends at the first */, wherever that is, which is why it fits inside a line, and also why it cannot nest.

  2. Question 2 of 18 Why does /* first /* second */ third */ stop a program from compiling when it sits between statements?

    Choose one answer.

    Show the answer: Question 2 of 18

    Answer: The comment ends at the first /, so third / is read as code

    Comments do not nest. The second /* is plain text inside the comment, and the first */ ends it, so the compiler then reads third */ as code and rejects it.

  3. Question 3 of 18 You need to switch off eight lines of a method for a test run, and two of them already hold a /* … */ comment. What is the safe way?

    Choose one answer.

    Show the answer: Question 3 of 18

    Answer: Put // in front of each of the eight lines

    Apply the rule that block comments do not nest to a new case: only // per line is safe, and deleting the lines is safer still, since version control keeps them.

  4. Question 4 of 18 What does the compiler do with Unicode escapes such as \u000a?

    Choose one answer.

    Show the answer: Question 4 of 18

    Answer: It replaces each one with its character before it looks for comments

    Unicode escapes are processed over the whole source file first. Only then does the compiler find comments and the rest of the code.

  5. Question 5 of 18 What does this print?

    Read the code, then choose one answer.

    int seats = 10;
    // seats are limited \u000a seats = 20;
    IO.println(seats);
    Show the answer: Question 5 of 18

    Answer: 20

    The compiler replaces Unicode escapes before it looks for comments, and \u000a is a line break. The comment ends there, so seats = 20; is a statement on a line of its own, and the program prints 20.

  6. Question 6 of 18 A teammate says a build with javac -Xlint:all would catch any line that a Unicode escape turns from comment into code. Is that right?

    Choose one answer.

    Show the answer: Question 6 of 18

    Answer: No, javac compiled UnicodeTrap.java with every warning on and said nothing

    Since the compiler sees nothing wrong, the protection has to come from somewhere else: reading code with a search for u000a and u000d, as the grep in the run did.

  7. Question 7 of 18 Which kind of comment does javadoc read as Markdown in Java 23 and later?

    Choose one answer.

    Show the answer: Question 7 of 18

    Answer: Consecutive lines that start with ///

    JEP 467 added Markdown documentation comments: each line starts with ///. /** … */ comments are still documentation comments, but written in HTML; /* … */ and ordinary // comments are ignored by javadoc.

  8. Question 8 of 18 A method takes a fee and a percentage, returns the discounted fee and throws IllegalArgumentException for a bad percentage. Which block tags does its comment need?

    Choose one answer.

    Show the answer: Question 8 of 18

    Answer: Two @param tags, one @return and one @throws

    discounted in Fees.java has exactly that set, and javadoc turned it into the Parameters, Returns and Throws parts of its page.

  9. Question 9 of 18 You move a comment that links to String#strip() from the HTML style to the Markdown style. How does the link change?
    Show the answer: Question 9 of 18

    Answer: {@link String#strip()} becomes [String#strip()]

    The table of the two styles in this lesson: <p> becomes a blank /// line, {@code x} becomes backticks, and {@link String} becomes [String]. The block tags stay the same.

  10. Question 10 of 18 Which javadoc option makes the run fail when doclint finds anything to warn about?

    Choose one answer.

    Show the answer: Question 10 of 18

    Answer: -Werror

    -Werror turns warnings into errors, so javadoc ends with a non-zero exit status. -Xdoclint:all decides what is checked, -quiet hides progress messages and -notimestamp leaves the time stamp out of the pages.

  11. Question 11 of 18 A method total(int[] prices) has a one-sentence /// comment and no tags. What does javadoc -Xdoclint:all report for it?

    Choose one answer.

    Show the answer: Question 11 of 18

    Answer: no @param for prices, and no @return

    HalfDone.java is this case: its run printed no @param for marks and no @return, and ended with status 0 until -Werror was added.

  12. Question 12 of 18 A team wants a pull request to fail when a new public method has no documentation. Which javadoc options do that?

    Choose one answer.

    Show the answer: Question 12 of 18

    Answer: -Xdoclint:all together with -Werror

    Combine the two runs of HalfDone.java: the same warnings, status 0 without -Werror and status 1 with it. The exercise of this lesson uses both options for that reason.

  13. Question 13 of 18 A static final field holds the largest number of seats in a room. Which name follows the Java conventions?

    Choose one answer.

    Show the answer: Question 13 of 18

    Answer: MAX_SEATS

    Constants are written in capital letters with underscores between the words. maxSeats is the style for variables and methods, MaxSeats for classes, and max_seats is not Java style at all.

  14. Question 14 of 18 A new class holds one fee receipt. Which name follows the conventions?

    Choose one answer.

    Show the answer: Question 14 of 18

    Answer: FeeReceipt

    The table of conventions: UpperCamelCase for classes, records, enums and interfaces, such as FeeReceipt and ArrayList.

  15. Question 15 of 18 Which of these compiles, yet breaks the Java naming conventions?
    Show the answer: Question 15 of 18

    Answer: int seats_left = 4;

    The compiler checks the rules, never the conventions: Identifiers.java compiled seats_left without complaint. Keeping to the conventions is up to the writer and the team.

  16. Question 16 of 18 What does final on a local variable mean?

    Choose one answer.

    Show the answer: Question 16 of 18

    Answer: It can be assigned only once

    final means assigned once. A constant is a static final field with a value fixed in the code, such as MAX_SEATS = 40.

  17. Question 17 of 18 Which comment is worth keeping above seats = seats + 1;?

    Choose one answer.

    Show the answer: Question 17 of 18

    Answer: // The organiser's seat is booked with the first student's.

    Let the code say what it does and the comment say why: the second table of the lesson compares the two kinds.

  18. Question 18 of 18 What happens with this code?

    Read the code, then choose one answer.

    final int[] seats = {40};
    seats[0] = 45;
    IO.println(seats[0]);
    Show the answer: Question 18 of 18

    Answer: It compiles and prints 45

    Transfer the rule "final means assigned once" to a reference: the variable may not change, but the object it refers to can, unless the object itself is immutable, as a String is.

Interview questions

Fresher · What kinds of comments does Java have, and which of them does javadoc read?

Java has end-of-line comments, from // to the end of the line, and block comments, from /* to the next */; block comments do not nest. Documentation comments are a third kind: /** … */ written in HTML with javadoc tags or, since Java 23, consecutive lines starting with ///, written in Markdown. The compiler ignores all of them. The javadoc tool reads only documentation comments, and only when they sit directly before a declaration such as a class, field, constructor or method; it turns them into HTML pages, with block tags such as @param, @return and @throws for the parameter, result and exception sections. A good answer adds one trap: Unicode escapes such as \u000a are processed before comments, so one can end a comment early.

Two longer questions of this module start from this lesson: a commented-out line in a pricing class that still runs, and what the Javadoc of a published library must promise.

Model answers open with any pass: ₹79 for 1 week ($2.99), one payment that never renews.

  1. Mid to senior

    In a code review you find // cap applies only to new users \u000d limit = 0; in a pricing class, and the author says it is only a comment. What does the compiler do with it, why does it matter for code review, and how would you stop such lines reaching the main branch?

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page. First step and follow-ups

  2. Mid to senior

    Your team publishes a small Java library. What must the Javadoc of a public method say, and how do you keep the documentation from drifting away from the code as the library changes?

    Model answer, Pro. First step and follow-ups

Key takeaways

  • // comments run to the end of the line and /* … */ comments to the first */, so block comments do not nest; switch code off with // on each line.
  • Unicode escapes are replaced before comments are found, so \u000a in a comment ends it, and the code after it runs.
  • Documentation comments sit directly above a declaration: /** … */ in HTML, or /// lines in Markdown from Java 23. Their first sentence is the summary, and @param, @return and @throws describe the rest.
  • javadoc -d docs writes the HTML, -Xdoclint:all reports missing comments and tags, and -Werror fails the run on any warning.
  • Packages are lowercase, types UpperCamelCase, methods and variables lowerCamelCase, constants UPPER_SNAKE_CASE.
  • final variables are assigned once and constants are static final; comment why, and let names say what.

Terms in this lesson

block tag
A tag at the end of a documentation comment that starts a section of the page: @param for a parameter, @return for the result and @throws for an exception, each followed by its description.
doclint
The checker inside javadoc and javac that reports problems in documentation comments, such as a public method with no comment, no @param for a parameter or no @return. -Xdoclint:all turns on every group of checks.
documentation comment
A comment directly above a class, field, constructor or method that the javadoc tool turns into HTML: /** … */ in HTML with tags, or, from Java 23, consecutive /// lines in Markdown. The compiler ignores it like any comment.
Unicode escape
A backslash, the letter u and four hexadecimal digits, such as \u000a, that stands for one character. The compiler replaces every one in a source file before it looks for comments, so \u000a in a comment is a real line break.

References

Related tools

Report a problem with this lesson

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.