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.
- 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,@sincee 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:
| Forma | Nome | Para quem |
|---|---|---|
// … | Comentário de linha | Quem lê o código: explica um detalhe da implementação |
/* … */ | Comentário de bloco | Quem 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 (ojavadocos 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
valorcom fonte de código no site. - */
- Fecha o comentário, logo antes do método.
"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
| Tag | Onde | O que descreve |
|---|---|---|
@param nome descrição | métodos e construtores | Um parâmetro (uma tag para cada, na ordem) |
@return descrição | métodos que não são void | O que o método devolve |
@throws Tipo descrição | métodos e construtores | Uma exceção possível e quando acontece (@exception é o nome antigo) |
@see referência | qualquer lugar | "Veja também": outro método ou classe |
@since versão | qualquer lugar | Desde que versão existe |
@author nome | classes | Quem escreveu |
@deprecated motivo | qualquer lugar | "Não use mais", e o que usar no lugar (junto com a anotação @Deprecated; veja Anotações) |
{@code texto} | dentro do texto | Mostra texto como código (e sem interpretar < como HTML) |
{@link Classe#metodo} | dentro do texto | Um 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
publicsem/** */. O construtor, os doisgete osacar. - warning: no @param for valor
- O
depositartem comentário, mas não descreve o parâmetrovalor. - 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ágina | O 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ção | Devolve o caractere na posição; as posições vão de 0 a length() - 1. |
| Parameters | index: a posição. |
| Returns | O char naquela posição. |
| Throws | IndexOutOfBoundsException 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
- Use a caixa de busca (Search) no alto: digite
Stringe escolhajava.lang.String; ou digite o nome de um método, comocharAt. - Na página da classe, leia a descrição do topo (muitas trazem exemplos de uso).
- 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…?".
- Clique no método para ver os detalhes: parâmetros, retorno, exceções.
- 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 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
| Item | O que faz |
|---|---|
/** … */ | Comentário de documentação, logo antes do item |
/// … | Comentário de documentação em Markdown (Java 23+) |
@param, @return, @throws | Parâmetros, retorno, exceções |
@see, @since, @author, @deprecated | Veja também, versão, autor, "não use mais" |
{@code …}, {@link …} | Código e link no meio do texto |
javadoc -d doc Arquivo.java | Gera o site na pasta doc |
javadoc -d doc -sourcepath src pacote | Gera 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:
3. Gerar o site
Complete para gerar a documentação de Agenda.java na pasta docs:
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.javagera o site;warning: no commenteno @paramsão avisos (o site sai com buracos);@param name not foundé erro.- Por padrão, só itens
publiceprotectedsã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.