Java Javadoc

Toda a documentação oficial do Java, aquela que explica o que faz cada método de String, Math ou ArrayList, foi escrita dentro do código-fonte, em comentários especiais, e transformada num site pela ferramenta javadoc. Você pode fazer o mesmo com as suas classes, e precisa saber ler esse formato para usar a biblioteca do Java.

Você vai aprender
  • A diferença entre //, /* */ e o comentário de documentação /** */.
  • Onde pôr um comentário de documentação e como escrevê-lo.
  • As tags @param, @return, @throws, @see, @since e os trechos {@code} e {@link}.
  • Gerar o site com javadoc -d doc … e entender os avisos (warning: no comment) e erros.
  • Os comentários em Markdown com /// (Java 23+).
  • Ler a documentação oficial da API.

A ideia: o manual que mora junto com a máquina

Pense no manual de um eletrodoméstico. Se ele fica numa gaveta separada, logo fica desatualizado: o fabricante muda um botão e esquece de mudar o manual. O Javadoc põe o manual colado em cada peça: o comentário fica logo acima do método que ele descreve. Quem muda o método vê o comentário na hora e o atualiza junto.

Esse comentário tem dois públicos:

  • Quem usa a sua classe (outra pessoa, ou você daqui a seis meses): lê o site gerado, ou a caixinha de ajuda que a IDE mostra ao passar o mouse sobre o método.
  • A ferramenta javadoc: lê os comentários e gera páginas HTML com índice, busca e links.

Três tipos de comentário

Você conheceu os comentários em Comentários. O terceiro tipo é o desta aula:

FormaNomePara quem
// …Comentário de linhaQuem lê o código: explica um detalhe da implementação
/* … */Comentário de blocoQuem lê o código: explicações mais longas
/** … */Comentário de documentação (Javadoc)Quem usa a classe: o que ela faz, não como

A única diferença visível é o segundo asterisco: /**. Para o compilador, os três são ignorados; para o javadoc, só o terceiro conta, e só quando está imediatamente antes de uma classe, um construtor, um método ou um atributo.


1. O primeiro comentário de documentação

/**
 * Coloca dinheiro na conta.
 *
 * @param valor quanto depositar; precisa ser maior que zero
 * @throws IllegalArgumentException se {@code valor} for zero ou negativo
 */
public void depositar(double valor) {
/**
Abre o comentário de documentação. Fica sozinho na linha.
* Coloca dinheiro na conta.
A descrição. A primeira frase (até o primeiro ponto) é o resumo, que aparece nas tabelas do site; capriche nela. Os * no começo das linhas são só enfeite (o javadoc os ignora), mas são o costume.
*
Uma linha vazia separa a descrição das tags.
@param valor …
Descreve o parâmetro valor: o nome tem de ser igual ao do método.
@throws IllegalArgumentException …
Descreve uma exceção que o método pode lançar, e quando.
{@code valor}
Mostra valor com fonte de código no site.
*/
Fecha o comentário, logo antes do método.
Descreva o que faz, não como faz

"Coloca dinheiro na conta" ajuda quem usa. "Soma valor ao atributo saldo com +=" não ajuda: isso está no código, e muda se a implementação mudar. Explique o comportamento visível: o que entra, o que sai, o que pode dar errado.

As tags principais

TagOndeO que descreve
@param nome descriçãométodos e construtoresUm parâmetro (uma tag para cada, na ordem)
@return descriçãométodos que não são voidO que o método devolve
@throws Tipo descriçãométodos e construtoresUma exceção possível e quando acontece (@exception é o nome antigo)
@see referênciaqualquer lugar"Veja também": outro método ou classe
@since versãoqualquer lugarDesde que versão existe
@author nomeclassesQuem escreveu
@deprecated motivoqualquer lugar"Não use mais", e o que usar no lugar (junto com a anotação @Deprecated; veja Anotações)
{@code texto}dentro do textoMostra texto como código (e sem interpretar < como HTML)
{@link Classe#metodo}dentro do textoUm link para outra parte da documentação

Dentro da descrição vale HTML simples: <p> para começar um parágrafo novo, <ul><li> para listas.

Missão: escreva o comentário de documentação do método formatar, logo acima dele: uma frase de resumo, um @param valor e um @return. O programa precisa continuar mostrando R$ 4,50.

public class Main {

    static String formatar(double valor) {
        return String.format("R$ %.2f", valor);
    }

    public static void main(String[] args) {
        System.out.println(formatar(4.5));
    }
}
public class Main {

    /**
     * Formata um valor em reais, com duas casas decimais.
     *
     * @param valor o valor a formatar
     * @return o texto formatado, como {@code R$ 4,50}
     */
    static String formatar(double valor) {
        return String.format("R$ %.2f", valor);
    }

    public static void main(String[] args) {
        System.out.println(formatar(4.5));
    }
}

2. Gerar a documentação: javadoc -d

A Ana começou a documentar a classe Conta (a mesma de Testes com JUnit), mas só escreveu dois comentários: o da classe e o do depositar, ainda sem @param.

package br.com.ana.banco;

/**
 * Uma conta bancária simples, com titular e saldo.
 */
public class Conta {
    private final String titular;
    private double saldo;

    public Conta(String titular) {
        this.titular = titular;
    }

    public String getTitular() {
        return titular;
    }

    public double getSaldo() {
        return saldo;
    }

    /**
     * Coloca dinheiro na conta.
     */
    public void depositar(double valor) {
        if (valor <= 0) {
            throw new IllegalArgumentException("Valor inválido: " + valor);
        }
        saldo += valor;
    }

    public void sacar(double valor) {
        if (valor <= 0) {
            throw new IllegalArgumentException("Valor inválido: " + valor);
        }
        if (valor > saldo) {
            throw new IllegalStateException("Saldo insuficiente");
        }
        saldo -= valor;
    }
}
$ javadoc -d doc src/br/com/ana/banco/Conta.java
Loading source file src/br/com/ana/banco/Conta.java...
Constructing Javadoc information...
Creating destination directory: "doc/"
Building index for all the packages and classes...
Standard Doclet version 25.0.4.1+1-LTS
Building tree for all the packages and classes...
Generating doc/br/com/ana/banco/Conta.html...
src/br/com/ana/banco/Conta.java:25: warning: no @param for valor
    public void depositar(double valor) {
                ^
src/br/com/ana/banco/Conta.java:10: warning: no comment
    public Conta(String titular) {
           ^
src/br/com/ana/banco/Conta.java:18: warning: no comment
    public double getSaldo() {
                  ^
src/br/com/ana/banco/Conta.java:14: warning: no comment
    public String getTitular() {
                  ^
src/br/com/ana/banco/Conta.java:32: warning: no comment
    public void sacar(double valor) {
                ^
Generating doc/br/com/ana/banco/package-summary.html...
Generating doc/br/com/ana/banco/package-tree.html...
Generating doc/overview-tree.html...
Generating doc/allclasses-index.html...
Building index for all classes...
Generating doc/allpackages-index.html...
Generating doc/index-all.html...
Generating doc/search.html...
Generating doc/index.html...
Generating doc/help-doc.html...
5 warnings
$ echo $?
0
javadoc
A ferramenta do JDK (vem junto com o javac).
-d doc
Destination: a pasta onde o site será criado. Sem o -d, os arquivos HTML se espalham na pasta atual.
src/br/com/ana/banco/Conta.java
Os arquivos a documentar (pode ser vários, ou *.java).
Generating …
Cada página criada: uma por classe (Conta.html), uma por pacote, índices, busca.
warning: no comment
"Sem comentário": um item public sem /** */. O construtor, os dois get e o sacar.
warning: no @param for valor
O depositar tem comentário, mas não descreve o parâmetro valor.
5 warnings / código 0
São avisos: o site foi gerado mesmo assim, só com buracos.

O formato dos avisos é o mesmo dos erros do javac (veja Lendo Erros do javac): arquivo:linha: warning: mensagem, a linha do código e um ^ apontando. Repare que os atributos private (titular, saldo) não geraram aviso: por padrão, o javadoc documenta só o que é public e protected, que é o que quem usa a classe consegue ver (veja Modificadores de Acesso).

A classe toda documentada

package br.com.ana.banco;

/**
 * Uma conta bancária simples, com titular e saldo.
 *
 * <p>A conta começa com saldo zero. Depósitos e saques
 * precisam ser positivos, e o saldo nunca fica negativo.
 *
 * @author Ana
 * @since 1.0
 */
public class Conta {
    private final String titular;
    private double saldo;

    /**
     * Cria uma conta vazia para o titular informado.
     *
     * @param titular o nome de quem é dono da conta
     */
    public Conta(String titular) {
        this.titular = titular;
    }

    /**
     * Devolve o nome do titular.
     *
     * @return o nome do dono da conta
     */
    public String getTitular() {
        return titular;
    }

    /**
     * Devolve o saldo atual.
     *
     * @return o saldo, em reais; nunca é negativo
     */
    public double getSaldo() {
        return saldo;
    }

    /**
     * Coloca dinheiro na conta.
     *
     * @param valor quanto depositar; precisa ser maior que zero
     * @throws IllegalArgumentException se {@code valor} for zero ou negativo
     */
    public void depositar(double valor) {
        if (valor <= 0) {
            throw new IllegalArgumentException("Valor inválido: " + valor);
        }
        saldo += valor;
    }

    /**
     * Tira dinheiro da conta.
     *
     * @param valor quanto sacar; precisa ser maior que zero
     * @throws IllegalArgumentException se {@code valor} for zero ou negativo
     * @throws IllegalStateException se {@code valor} for maior que o saldo
     * @see #depositar(double)
     */
    public void sacar(double valor) {
        if (valor <= 0) {
            throw new IllegalArgumentException("Valor inválido: " + valor);
        }
        if (valor > saldo) {
            throw new IllegalStateException("Saldo insuficiente");
        }
        saldo -= valor;
    }
}

Agora o javadoc não reclama de nada. A opção -quiet ("quieto") esconde as linhas Loading…/Generating… e deixa só avisos e erros; sem nenhum, não aparece nada:

$ rm -r doc
$ javadoc -d doc src/br/com/ana/banco/Conta.java
Loading source file src/br/com/ana/banco/Conta.java...
Constructing Javadoc information...
Creating destination directory: "doc/"
Building index for all the packages and classes...
Standard Doclet version 25.0.4.1+1-LTS
Building tree for all the packages and classes...
Generating doc/br/com/ana/banco/Conta.html...
Generating doc/br/com/ana/banco/package-summary.html...
…                                                    « as mesmas páginas de antes, sem nenhum warning
Generating doc/help-doc.html...
$ javadoc -quiet -d doc src/br/com/ana/banco/Conta.java
$ echo $?
0

O site gerado

$ ls doc
allclasses-index.html
allpackages-index.html
br
element-list
help-doc.html
index-all.html
index.html
legal
member-search-index.js
module-search-index.js
overview-tree.html
package-search-index.js
resource-files
script-files
search.html
tag-search-index.js
type-search-index.js

Abra doc/index.html no navegador (no Linux: xdg-open doc/index.html). Você verá um site com a mesma cara da documentação oficial do Java: o pacote br.com.ana.banco, a classe Conta com a descrição, um resumo do construtor e dos métodos (com a primeira frase de cada comentário), e, mais abaixo, os detalhes de cada método com as seções Parameters, Returns, Throws e See Also montadas a partir das suas tags. Há também uma caixa de busca no alto.

Documentar um pacote inteiro

Em vez de listar arquivos, dá para indicar a pasta dos fontes (-sourcepath) e o nome do pacote:

$ javadoc -d doc -sourcepath src br.com.ana.banco
Loading source files for package br.com.ana.banco...
Constructing Javadoc information...
…

Em projetos Maven, quem faz isso é o plugin maven-javadoc-plugin (mvn javadoc:javadoc); no Gradle, a tarefa ./gradlew javadoc.


3. Comentários em Markdown: /// Java 23+

Desde o Java 23, você pode escrever a documentação em Markdown (o formato de texto simples usado em sites como o GitHub), começando cada linha com /// em vez de usar /** */. Código vai entre crases, em vez de {@code}; as tags @param e @return continuam iguais:

/// Formata valores em reais.
///
/// Exemplo: `Moeda.formatar(4.5)` devolve `R$ 4,50`.
public class Moeda {

    /// Cria o utilitário (não é preciso: os métodos são estáticos).
    public Moeda() {
    }

    /// Formata um valor com duas casas decimais.
    ///
    /// @param valor o valor em reais
    /// @return o texto formatado, como `R$ 4,50`
    public static String formatar(double valor) {
        return String.format("R$ %.2f", valor);
    }
}
$ javadoc -quiet -d doc Moeda.java
$ echo $?
0
$ grep -o "<code>R\$ 4,50</code>" doc/Moeda.html | head -2
<code>R$ 4,50</code>                « as crases viraram código no HTML
<code>R$ 4,50</code>

Em código anterior ao Java 23 (e na maior parte do código que você vai ler), o formato é o /** */; os dois funcionam no JDK 25. Escolha um e use sempre o mesmo no projeto.


4. Ler a documentação oficial da API

A biblioteca do Java (veja A Biblioteca Padrão) tem milhares de classes, e ninguém decora. O que todo programador faz é consultar a documentação, que fica em:

https://docs.oracle.com/en/java/javase/25/docs/api/

Ela foi gerada pelo mesmo javadoc, a partir dos comentários do código-fonte do JDK. O código-fonte vem junto com o JDK, no arquivo lib/src.zip, e dá para ver o comentário original do charAt da String:

$ unzip -p /opt/jdk-25/lib/src.zip java.base/java/lang/String.java | grep -n -B18 "public char charAt(int index)"
1604-    /**
1605-     * Returns the {@code char} value at the
1606-     * specified index. An index ranges from {@code 0} to
1607-     * {@code length() - 1}. The first {@code char} value of the sequence
1608-     * is at index {@code 0}, the next at index {@code 1},
1609-     * and so on, as for array indexing.
1610-     *
1611-     * <p>If the {@code char} value specified by the index is a
1612-     * <a href="Character.html#unicode">surrogate</a>, the surrogate
1613-     * value is returned.
1614-     *
1615-     * @param      index   the index of the {@code char} value.
1616-     * @return     the {@code char} value at the specified index of this string.
1617-     *             The first {@code char} value is at index {@code 0}.
1618-     * @throws     IndexOutOfBoundsException  if the {@code index}
1619-     *             argument is negative or not less than the length of this
1620-     *             string.
1621-     */
1622:    public char charAt(int index) {

Exatamente as mesmas tags que você usou na Conta. No site, esse comentário vira a entrada do método charAt da página da String. Como ler uma entrada de método:

Parte da páginaO que diz (no charAt)
Assinatura: public char charAt(int index)Recebe um int, devolve um char; é de objeto (não tem static), então se usa texto.charAt(0).
DescriçãoDevolve o caractere na posição; as posições vão de 0 a length() - 1.
Parametersindex: a posição.
ReturnsO char naquela posição.
ThrowsIndexOutOfBoundsException se o índice for negativo ou não for menor que o tamanho. Ou seja: "Ana".charAt(3) quebra.
Since (em outros métodos)A versão do Java em que o método apareceu. Útil para saber se você pode usá-lo, por exemplo, num sistema com Java 11.

Como navegar

  1. Use a caixa de busca (Search) no alto: digite String e escolha java.lang.String; ou digite o nome de um método, como charAt.
  2. Na página da classe, leia a descrição do topo (muitas trazem exemplos de uso).
  3. Vá ao Method Summary, a tabela com todos os métodos e o resumo de cada um. É o lugar para descobrir "existe um método que faz…?".
  4. Clique no método para ver os detalhes: parâmetros, retorno, exceções.
  5. Repare em Methods declared in class …: os métodos herdados (veja Herança) aparecem listados separadamente.

A organização é por módulo (java.base tem o essencial; veja Módulos), depois pacote (java.lang, java.util…), depois classe. A documentação está em inglês; o tradutor do navegador ajuda, mas os nomes de métodos e as tags (Parameters, Returns) você logo reconhece. Nas IDEs, o mesmo texto aparece ao passar o mouse sobre um método (ou com Ctrl+Q no IntelliJ).


Quando dá errado

error: @param name not found

A Ana mudou o nome no @param do sacar para quantia, mas o parâmetro continua se chamando valor:

$ javadoc -quiet -d doc src/br/com/ana/banco/Conta.java
src/br/com/ana/banco/Conta.java:59: error: @param name not found
     * @param quantia quanto sacar; precisa ser maior que zero
              ^
src/br/com/ana/banco/Conta.java:64: warning: no @param for valor
    public void sacar(double valor) {
                ^
1 error
1 warning
$ echo $?
1

O que aconteceu: o nome do @param tem de ser igual ao do parâmetro. Este é um erro (não um aviso): o código de saída é 1. Acontece muito quando se renomeia um parâmetro e se esquece o comentário. Como resolver: deixe os nomes iguais.

warning: use of default constructor, which does not provide a comment
$ javadoc -quiet -d doc Moeda.java
Moeda.java:4: warning: use of default constructor, which does not provide a comment
public class Moeda {
       ^
1 warning

O que aconteceu: a classe não declara construtor, então o Java cria um construtor público vazio (o "construtor padrão", veja Construtores), que entra na documentação sem descrição. Como resolver: declare o construtor e documente-o (como na Moeda com ///), ou torne-o private se a classe só tem métodos static.

O comentário não aparece no site

O que aconteceu: uma destas três: começou com /* (um asterisco só); há algo entre o comentário e o método (um import, outro comentário… anotações como @Override podem ficar no meio); ou o item não é public/protected. Como resolver: confira o /** e a posição. Para incluir itens privados, use javadoc -private.


Referência

ItemO que faz
/** … */Comentário de documentação, logo antes do item
/// …Comentário de documentação em Markdown (Java 23+)
@param, @return, @throwsParâmetros, retorno, exceções
@see, @since, @author, @deprecatedVeja também, versão, autor, "não use mais"
{@code …}, {@link …}Código e link no meio do texto
javadoc -d doc Arquivo.javaGera o site na pasta doc
javadoc -d doc -sourcepath src pacoteGera para um pacote inteiro
javadoc -quiet …Mostra só avisos e erros
javadoc -private …Inclui também os itens privados
docs.oracle.com/en/java/javase/25/docs/api/A documentação oficial do Java 25

Exercícios

1. Abrir o comentário

Complete com o que abre um comentário de documentação:


* Calcula a média das notas.
*/

2. A tag do retorno

Complete a tag que descreve o que o método devolve:

* a média, entre 0 e 10

3. Gerar o site

Complete para gerar a documentação de Agenda.java na pasta docs:

javadoc Agenda.java

4. O javadoc terminou com 4 warnings e código 0. O que aconteceu?

5. Qual comentário o javadoc usa para documentar o método logo abaixo?

6. Na documentação de um método, a seção Throws diz IndexOutOfBoundsException "if the index argument is negative". O que isso significa para você?

Missão final: documente o método sacar com uma frase de resumo, @param valor e @throws IllegalStateException dizendo quando ela acontece. O programa deve continuar mostrando Saldo insuficiente.

public class Main {
    static double saldo = 100.0;

    static void sacar(double valor) {
        if (valor > saldo) {
            throw new IllegalStateException("Saldo insuficiente");
        }
        saldo -= valor;
    }

    public static void main(String[] args) {
        try {
            sacar(500.0);
        } catch (IllegalStateException e) {
            System.out.println(e.getMessage());
        }
    }
}
public class Main {
    static double saldo = 100.0;

    /**
     * Tira dinheiro do saldo.
     *
     * @param valor quanto sacar
     * @throws IllegalStateException se {@code valor} for maior que o saldo
     */
    static void sacar(double valor) {
        if (valor > saldo) {
            throw new IllegalStateException("Saldo insuficiente");
        }
        saldo -= valor;
    }

    public static void main(String[] args) {
        try {
            sacar(500.0);
        } catch (IllegalStateException e) {
            System.out.println(e.getMessage());
        }
    }
}

Resumo

  • /** */ logo antes de uma classe, construtor, método ou atributo é um comentário de documentação; // e /* */ não entram na documentação.
  • A primeira frase é o resumo. Depois, as tags: @param (uma por parâmetro, com o nome exato), @return, @throws, @see, @since. No texto: {@code} e {@link}.
  • Descreva o que o método faz para quem usa, não como foi implementado.
  • javadoc -d doc Arquivos.java gera o site; warning: no comment e no @param são avisos (o site sai com buracos); @param name not found é erro.
  • Por padrão, só itens public e protected são documentados.
  • Java 23+: comentários em Markdown com ///.
  • A documentação oficial (docs.oracle.com/en/java/javase/25/docs/api/) é feita do mesmo jeito: leia a assinatura, a descrição, Parameters, Returns e Throws.