Refelection & Java Doc ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-10-31

Javadoc in Java: Documentation Comments and Tags

The line * Returns a List<String> of product names in a method comment looks harmless, yet the javadoc command answers it with error: unknown tag: String, and mvn javadoc:jar fails right before you publish your library. Javadoc reads the comment as HTML, and <String> is an unknown tag to it. Below is how to write such comments correctly.

Javadoc is the documentation generator for Java: it builds HTML documentation from special /** ... */ comments in the source code. It ships with the JDK as the javadoc command, and the official Java SE API documentation is generated with it.

1. What is Javadoc in Java

Javadoc solves the main problem of documentation — drifting away from the code. You describe a class or method in a comment right above its declaration, and the javadoc command collects these comments from all source files and builds a linked set of HTML pages: one page per class, package lists, an index and a search box.

When documentation lives in a separate file, every change to a method means finding and updating the matching section somewhere else — and sooner or later someone forgets. When the description sits next to the code, you see it on every change, the IDE shows it in tooltips, and the HTML version is rebuilt with one command.

Javadoc comments are used to document:

  • classes, interfaces, enums and records;
  • fields;
  • constructors and methods;
  • packages (the package-info.java file) and modules (module-info.java).

2. Javadoc comment syntax

A Javadoc comment (doc comment) starts with /** (two asterisks), ends with */ and is placed directly before the declaration of a class, field, constructor or method — before any annotations and modifiers. It consists of a main description followed by block tags. Regular /* ... */ and // comments are ignored by javadoc.

/**
 * Returns the sum of two numbers.
 * <p>
 * Overflow is not checked: for large values
 * use {@link Math#addExact(int, int)}.
 *
 * @param a the first operand
 * @param b the second operand
 * @return the sum {@code a + b}
 */
public static int sum(int a, int b) {
    return a + b;
}

Here the first line is the summary, {@link ...} is an inline tag inside the text, and @param and @return are block tags. The rules that shape the generated page:

  • The first sentence (up to the first period followed by a space) goes into the summary tables of the package and the class. Write it as a self-contained short description. In English text this rule bites on abbreviations: in Parses the input, e.g. a CSV line. the summary ends after «e.g.».
  • Leading asterisks and the spaces before them are discarded — they exist only for readability.
  • The text is HTML. Separate paragraphs with <p>, make lists with <ul>/<li>. Javadoc generates the <h1> of the page itself, so headings inside a comment should be <h2> or lower — and most comments need no headings at all.
  • Block tags start with @ and must be the first thing on a line (after the optional *). They come after the description: everything below the first block tag no longer belongs to the description.
  • Inline tags are written in curly braces, such as {@code} or {@link}, and can appear anywhere in the text.

3. Javadoc tags: list and purpose

In everyday code you mostly need @param, @return and @throws for methods, {@code} and {@link} inside the text, and @deprecated for outdated API. The other tags in the table are less common, but it pays to recognize them in other people’s code and in the JDK sources.

Tag What it does Where it applies Note
@param name description Describes a parameter Method, constructor; a type parameter — @param <T> The name must match the parameter in the signature, otherwise doclint reports an error
@return description Describes the return value Method (not void) Since Java 16 there is an inline form {@return ...}: it is both the first sentence and the Returns section
@throws Class description Describes an exception and the condition under which it is thrown Method, constructor @exception is the old synonym; document unchecked exceptions too (IllegalArgumentException)
@author name Author Class, interface, package Appears in the HTML only with the -author option
@version text Version of the class Class, interface, package Appears only with the -version option
@since version The API version in which the element appeared Any element The JDK uses @since 1.8, @since 21
@see reference Adds a See Also section Any element Forms: @see Cart#total(), @see "text", @see <a href="...">
@deprecated explanation Explains why the element is outdated and what to use instead Any element Used together with the @Deprecated annotation: the tag puts text into the docs, the annotation makes the compiler warn
{@link Class#member}, {@linkplain ...} A link to a class, method or field inside the text Any text For a method with parameters list the types: {@link String#indexOf(int)}; linkplain renders the link in plain font
{@code text} Code in monospace font Any text Escapes <, >, & by itself — unlike the HTML <code> tag
{@value}, {@value Class#FIELD} Inserts the value of a constant A static final constant, or a reference to one from any comment Works only for compile-time constants (primitives and String)
{@inheritDoc} Copies the description from the overridden method Overriding method If the method has no comment of its own, the description is inherited even without the tag
{@snippet : ...} A code example with highlighting and checkable regions Any text Since Java 18 (JEP 413), replaces the <pre>{@code ...}</pre> combination

For a generic method, the type parameter is documented with angle brackets: @param <T> the element type (type parameters are explained in Java Generics). For the difference between checked and unchecked exceptions that you list in @throws, see Java exceptions.

Where did the author go?

The @author and @version tags are in the source, but the generated page does not show them? That is expected: javadoc prints them only when the command includes the -author and -version options. Many teams skip @author altogether — Git already shows who wrote each line.

4. Javadoc example: documenting a class

A good Javadoc comment answers the questions the signature cannot: which values are allowed, what comes back in an edge case and which exception is thrown on error. Below is a shopping cart class documented by the book: a class description, a constant with {@value}, a method with @param, @return and @throws, and a deprecated method.

package com.example.shop;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Shopping cart of an online store: keeps items and calculates the total.
 * <p>
 * Usage example:
 * <pre>{@code
 * Cart cart = new Cart();
 * cart.add("Book", 500.0);
 * double sum = cart.total(); // 500.0
 * }</pre>
 *
 * @author Tatyana Milkina
 * @version 1.2
 * @since 1.0
 */
public class Cart {

    /** Maximum number of items in the cart: {@value}. */
    public static final int MAX_ITEMS = 50;

    private final List<String> items = new ArrayList<>();
    private double total;

    /**
     * Adds an item to the cart.
     *
     * @param name  item name, not {@code null}
     * @param price unit price, greater than zero
     * @return the number of items in the cart after adding
     * @throws NullPointerException     if {@code name == null}
     * @throws IllegalArgumentException if {@code price <= 0}
     * @throws IllegalStateException    if the cart already holds {@value #MAX_ITEMS} items
     * @see #total()
     */
    public int add(String name, double price) {
        Objects.requireNonNull(name, "name");
        if (price <= 0) {
            throw new IllegalArgumentException("Price must be greater than zero: " + price);
        }
        if (items.size() >= MAX_ITEMS) {
            throw new IllegalStateException("Cart is full");
        }
        items.add(name);
        total += price;
        return items.size();
    }

    /**
     * Returns the total price of all items in the cart.
     *
     * @return the total; {@code 0.0} if the cart is empty
     */
    public double total() {
        return total;
    }

    /**
     * Returns the total rounded to a whole number.
     *
     * @return the total rounded as by {@link Math#round(double)}
     * @deprecated rounding loses cents; use {@link #total()}
     */
    @Deprecated(since = "1.2", forRemoval = true)
    public long totalRounded() {
        return Math.round(total);
    }
}

What you get on the HTML page of the Cart class:

  • the MAX_ITEMS field reads «Maximum number of items in the cart: 50.» — {@value} inserted the value of the constant;
  • the add method gets Parameters, Returns, Throws and See Also sections, the last one linking to total();
  • totalRounded() lands in the Deprecated list, marked for removal (forRemoval = true), and calling it from another class produces a compiler warning;
  • the private fields items and total do not appear on the page: by default only public and protected elements are documented.

5. How to generate Javadoc: the javadoc command, Maven and Gradle

To generate Javadoc, run the javadoc command from the JDK: pass it the source files or packages and an output directory (-d). In Maven and Gradle projects a single build task does the same job, so you do not call javadoc by hand.

For the class from the example above (sources in the src directory):

javadoc -d docs -sourcepath src -subpackages com.example -author -version -encoding UTF-8

Shortened output of the command:

Loading source files for package com.example.shop...
Constructing Javadoc information...
Building index for all the packages and classes...
Generating docs/com/example/shop/Cart.html...
...

The docs directory now contains the HTML files: index.html (the entry point), a page per class (com/example/shop/Cart.html), the package summary package-summary.html, the class hierarchy overview-tree.html, the alphabetical index index-all.html, and lists of deprecated elements and constant values. Since JDK 9 the generated docs also have a search box.

Option What it does
-d directory Where to write the HTML (without it — the current directory)
-sourcepath, -subpackages Where to look for sources and which packages to process (including subpackages)
-author, -version Include the @author and @version tags in the output
-private Document all elements, including private (default — only public and protected)
-encoding UTF-8 Encoding of the source files. Needed for non-ASCII characters in comments on JDKs older than 18 on Windows; since JDK 18 UTF-8 is the default (JEP 400)
-Xdoclint:none Turns off the doclint checks (fixing the comments is better than switching the check off)

With build tools:

# Maven: HTML documentation of the project
mvn javadoc:javadoc

# Maven: *-javadoc.jar archive (required for publishing to Maven Central)
mvn javadoc:jar

# Gradle: output in build/docs/javadoc
./gradlew javadoc

The full list of options is in the javadoc command reference.

6. Javadoc in the IDE

Most of the time you read Javadoc not in a browser but in the IDE: it shows a method comment in a popup straight from the sources, without generating any HTML. In IntelliJ IDEA the Quick Documentation popup opens with Ctrl+Q on Windows and Linux or F1 on macOS, and also on mouse hover over a name.

The IDE also helps you write comments: type /** above a method in IntelliJ IDEA or Eclipse and press Enter, and you get a template with @param, @return and @throws taken from the method signature. All that is left is to fill in the descriptions.

7. Common Javadoc mistakes and doclint errors

Since Java 8 the javadoc command checks comments with the built-in doclint analyzer by default. Its most frequent complaints are generic angle brackets and a bare < in the text, wrong names in @param, and self-closing HTML tags such as <p/>. Doclint errors stop a mvn javadoc:jar build.

What will javadoc say about this comment?

/**
 * Returns a List<String> of product names if a < b.
 *
 * @param a the lower bound
 * @param c the upper bound
 */
public List<String> names(int a, int b) { ... }
error: unknown tag: String
error: malformed HTML
error: @param name not found
warning: no @param for b

Breakdown: javadoc takes <String> for an HTML tag and the lone < for the start of a broken tag, while @param c does not match the parameter b in the signature. The fixed version:

/**
 * Returns a {@code List<String>} of product names if {@code a < b}.
 *
 * @param a the lower bound
 * @param b the upper bound
 * @return the list of names; empty if there are no products
 */
public List<String> names(int a, int b) { ... }

A few more slips that are easy to make:

  • The comment repeats the method name. /** Returns the name. */ above getName() adds nothing; it is more useful to say whether the result can be null.
  • The comment comes after an annotation. Put /** ... */ before the annotations: that way both javadoc and the IDE reliably attach it to the declaration.
  • The docs fall behind the code. The method started throwing a new exception, but nobody added @throws — API users find out only from a stack trace.

{@code} instead of <code>

Inside the HTML <code> tag you still have to escape angle brackets (<), otherwise doclint reports an error. The inline tag {@code ...} escapes them for you, so use it for code with generics and comparison operators.

Frequently asked questions

Do Javadoc comments end up in the compiled .class file?

No. The compiler drops all comments, including /** ... */, so Javadoc is read only from the sources. That is why libraries publish separate *-sources.jar and *-javadoc.jar archives, and why reflection cannot read Javadoc text at runtime. The @Deprecated annotation does get into the bytecode, but the text of the @deprecated tag does not.

Should I write Javadoc for private methods and getters?

It is a must for the public API: public and protected classes and methods that other code uses. For private methods javadoc generates nothing by default, so a clear name and, if needed, a regular comment are enough. Document trivial getters only when there is something to say beyond the name: whether null can come back, or whether it is a copy or a reference to an internal object.

Why does my IDE show no documentation for a library method?

Most likely the project has only the jar with bytecode, and it contains no comments. Download the sources or the javadoc archive of the library: in IntelliJ IDEA use Download Sources in the opened decompiled class or the matching action in the Maven tool window. After that Ctrl+Q shows the full description.

Can I write Javadoc in Markdown?

Yes, since Java 23 (JEP 467). A Markdown doc comment is written as lines starting with ///, without /** and asterisks; the @param and @return tags work the same way, and links are written as [String#indexOf(int)]. Projects on older JDKs keep the classic HTML format from this lesson.

Comments

Please log in or register to have a possibility to add comment.