Java文档注释的全面指南
1. 文档注释的结构
文档注释以
/**
开头,以
*/
结尾。每个文档注释描述紧随其后声明的标识符。注释行开头的
*
字符和
*
前面的空白字符会被忽略。注释的第一句是该标识符的摘要,“句子”指的是到第一个后面带有空白字符的句号为止的所有文本。
例如:
/**
* Do what the invoker intends. "Intention" is defined by
* an analysis of past behavior as described in ISO 4074-6.
*/
public void dwim() throws IntentUnknownException;
此方法
dwim
的摘要为 “Do what the invoker intends.”。文档注释的第一句应是一个好的摘要。
HTML 标签常被嵌入文档注释中,用作格式指令或指向其他文档的交叉引用链接。几乎可以使用任何标准 HTML 标签,但使用
<h1>
、
<h2>
等标题标签时要小心,因为它们可能会破坏整体文档的结构,不过在类和包文档中使用通常是安全的。要插入字符
<
、
>
或
&
,应分别使用
<
、
>
或
&
。如果一行开头必须有
@
,则使用
@
,否则
@
会被视为文档注释标签的开始。
只有紧接在类、接口、方法或字段之前的文档注释才会被处理。如果文档注释与其描述的内容之间有除空白、注释或注解之外的任何内容,该文档注释将被忽略。例如,若在文件顶部放置一个文档注释,且在该注释与类之间有包或导入语句,那么该文档注释将不会被使用。文档注释适用于在单个语句中声明的所有字段,因此在使用文档注释时,通常应避免在单个语句中声明多个字段。
2. 标签
文档注释可以包含携带特定信息的标签,标签有两种形式:
-
块标签
:定义独立的文本元素,所有块标签都以
@
开头,如
@see
或
@deprecated
。这些段落在生成的文档中会被特殊处理,产生标记段落、指向其他文档的链接等特殊效果。
-
行内标签
:可以出现在文档注释文本的任何位置,用于应用特殊格式,如
{@code}
用于使用代码字体,或生成特殊文本,如使用
{@link}
创建超文本链接。行内标签的形式为
{@tag-name args}
,其中可选的
args
值可能提供要格式化的文本或链接的目标。
除了带标签的段落和行内标签,文档注释中的文本被视为 HTML 的输入文本。可以使用标准的
<p>
标签创建文档中的段落分隔,使用
<pre>
创建示例代码块等。并非所有标签都需要由
javadoc
工具默认处理,具体处理哪些标签的详细信息请参考工具文档。
2.1 @see
@see
标签用于创建指向其他
javadoc
文档的交叉引用链接。可以指定任何标识符,但必须进行充分限定。例如,通常可以使用类成员的简单名称,但如果该成员是重载方法,则必须通过列出参数类型来指定要引用的重载方法。可以使用未限定名称指定当前包中的接口或类,但必须使用完全限定名称指定其他包中的类型。通过在成员名称前加
#
来指定类型的成员。以下是一些可能有效的
@see
标签示例:
@see #getName
@see Attr
@see com.magic.attr.Attr
@see com.magic.attr.Deck#DECK_SIZE
@see com.magic.attr.Attr#getName
@see com.magic.attr.Attr#Attr(String)
@see com.magic.attr.Attr#Attr(String, Object)
@see com.magic.attr
@see <a href="spec.html#attr">Attribute Specification</a>
@see "The Java Developer's Almanac"
-
第一种形式引用与文档注释所在的同一类或接口,或任何包含的类或接口中的
getName方法,同样的语法也适用于构造函数和字段。 - 第二种形式引用当前包或导入包中的类。
- 第三种形式通过完全限定名称引用类。
-
接下来的四种形式引用成员,前两种展示了字段(
DECK_SIZE)或方法(getName)的形式。可以直接使用方法名,因为在Attr类中只定义了一个getName方法。后两种形式引用Attr类的构造函数,一个接受String参数,另一个接受String和Object参数。当构造函数或方法重载时,必须指定要引用的方法的参数。 -
下一种
@see形式将读者指向特定的包:com.magic.attr。 -
最后两种形式允许引用其他文档,第一种使用
<a...>定义链接,第二种使用引号括起文档名称。
命名语言实体的
@see
形式(除最后两种外的任何上述形式)可以在实体后面跟一个标签,该标签名称将在生成的文档中使用,而不是实体的名称。例如:
@see #getName Attribute Names
这将创建一个指向
getName
文档的链接,但显示的文本为 “Attribute Names” 而不是 “getName”。通常应使用实际的成员名称,但偶尔可能会发现此功能很有用。
2.2 {@link} 和 {@linkplain}
@see
标签适用于文档末尾的 “See also” 部分。当交叉引用应包含在注释文本中时,可以在文本中嵌入
{@link}
行内标签。
@link
的语法为:
{@link package.class#member [label]}
标识符的规范与
@see
相同,可选标签也相同。以下句子嵌入了一个指向
getValue
方法的链接:
Changes the value returned by calls to {@link #getValue}.
{@linkplain}
标签的作用与
{@link}
相同,只是生成的文本使用普通字体而不是代码字体,这对于用纯文本标签替换链接很有用。
2.3 @param
@param
标签用于记录方法或构造函数的单个参数,或类、接口或泛型方法中的类型参数。如果使用
@param
标签,应该为方法的每个参数都有一个标签。段落的第一个单词被视为参数名称,其余部分是其描述:
@param max The maximum number of words to read.
在记录类型参数时,应在类型参数名称周围使用
<
和
>
:
@param <E> The element type of this List
通常,类型参数不需要显式文档,因为它们的含义很明显。
2.4 @return
@return
标签用于记录方法的返回值:
@return The number of words actually read.
2.5 @throws 和 @exception
@throws
标签用于记录方法或构造函数抛出的异常。如果使用
@throws
标签,应该为方法抛出的每种类型的异常都有一个标签。这个列表通常包括比必须在
throws
子句中声明的受检查异常更多的异常,无论是否需要,在
throws
子句中声明所有异常是个好主意,使用
@throws
标签时也是如此。例如,假设方法检查其参数以确保没有参数为
null
,如果发现
null
参数则抛出
NullPointerException
,那么应该在
throws
子句和
@throws
标签中声明
NullPointerException
。
@throws UnknownName The name is unknown.
@throws java.io.IOException
Reading the input stream failed; this exception
is passed through from the input stream.
@throws NullPointerException
The name is <code>null</code>.
@exception
标签与
@throws
等效。
2.6 @deprecated
@deprecated
标签将标识符标记为已弃用,即不适合继续使用。使用已弃用的类型、构造函数、方法或字段的代码在编译时可能会生成警告。应该确保已弃用的实体继续工作,以免破坏尚未更新的现有代码。弃用有助于鼓励代码用户更新到最新版本,同时保留现有代码的完整性。用户可以在他们选择的时候转向新机制,而不是在发布类型的新版本时被迫立即转向。应该为已弃用的实体指明替代方案:
/**
* Do what the invoker intends. "Intention" is defined by
* an analysis of past behavior as described in ISO 4074-6.
*
* @deprecated You should use dwishm instead
* @see #dwishm
*/
@Deprecated
public void dwim() throws IntentUnknownException;
虽然编译器在看到
@deprecated
标签时可能会生成警告,但如果看到
@Deprecated
注解,则一定会生成警告。应该始终同时使用这两者:使用
@deprecated
标签记录弃用的原因,使用
@Deprecated
注解通知编译器。
2.7 @author
@author
标签用于指定类或接口的作者:
@author Aristophanes
@author Ursula K. LeGuin
@author Ibid
可以根据需要指定任意数量的
@author
段落。为了在所有情况下都能获得一致的输出,每个
@author
段落应该只指定一个作者。
2.8 @version
@version
标签用于指定类或接口的任意版本规范:
@version 1.1
2.9 @since
@since
标签用于指定一个任意的版本规范,表示带标签的实体何时被添加到系统中:
@since 2.1
标记“诞生版本”有助于跟踪哪些实体较新,因此可能需要加强文档或测试。按照惯例,类或接口上的
@since
标签适用于该类或接口中没有自己的
@since
标签的所有成员。例如,如果上述
@since
标签位于一个类之前,那么该类的所有构造函数、字段和方法都将被假定在版本 2.1 中就已经存在,除非有例如
@since 2.2
标签的成员。
2.10 {@literal} 和 {@code}
{@literal text}
行内标签会使文本按原样打印,而不会被解释为 HTML 源。这意味着可以使用
&
、
<
和
>
,而不是
&
、
<
和
>
。
{@code text}
行内标签的行为与
{@literal text}
完全相同,只是文本以代码字体打印,与将
{@literal text}
标签用
<code>
和
</code>
HTML 标签包裹的效果相同。这些行内标签在编写关于泛型类型的内容时非常方便。
2.11 {@value}
{@value static-field-name}
标签会被指定的常量静态字段的实际值替换,该标签使用与
@see
标签相同的成员语法。例如,如果文档注释包含以下文本:
The valid range is 0 to {@value java.lang.Short#MAX_VALUE}.
则生成的文本将是:
The valid range is 0 to 32767.
为了方便起见,正在记录的常量静态字段的值可以通过
{@value}
引用,而无需指定字段名称。例如:
/** The default capacity of a new queue ({@value}). */
static final int DEFAULT_CAPACITY = 10;
生成的文本将是:
The default capacity of a new queue (10).
在指定特定的字段成员时,要注意不要在成员名称和右花括号之间留下任何空白,因为它将被视为名称的一部分。所有常量字段都在
javadoc
工具生成的 “Constant Field Values” 页面上进行记录。
2.12 {@docRoot}
javadoc
生成的文件被放入一个树结构中,子目录包含文档的各个部分。文件在树中的具体位置取决于
javadoc
的实现,并且可能会根据环境、用户偏好等因素而变化。在构建树之后,可能需要向其中添加内容,然后在文档注释中引用这些添加的部分。行内
{@docRoot}
标签允许在文档注释中放入对文档树中其他文件的相对引用,
{@docRoot}
标签将被替换为生成的文档树顶部的相对路径。例如,以下句子:
Check out <a href="{@docRoot}/license.html">our license</a>.
将生成一个带有指向文档树根目录下
license.html
文件链接的句子。从文档注释生成文档后,可以将
license.html
复制到生成的文档树的顶部,上述链接将始终从生成的输出指向
license.html
文件。对于某些应用程序,可能会发现 “The doc-files Directory” 中描述的机制更有用。
2.13 {@inheritDoc}
{@inheritDoc}
标签用于从超类型复制文档注释,这将在下一节讨论。
3. 继承方法文档注释
如果没有为继承的方法提供文档注释,该方法将“继承”超类型的文档注释。这通常就足够了,特别是当一个类实现一个接口时,实现中的方法通常只需执行接口指定的操作,或者至少没有什么需要包含在文档注释中的内容。如果必须将接口或超类的所有文档注释复制到定义重写方法的类中,那将非常不方便。
在继承文档注释时,应该添加一个明确的注释,以免阅读代码的人认为忘记了为方法添加文档,例如:
// inherit doc comment
public void dwim() throws IntentUnknownException {
// ...
}
虽然重写接口方法可能不需要对文档进行任何更改,但重写超类方法很可能涉及对方法契约的更改,如弱化参数的前置条件、强化返回值的后置条件或减少可能抛出的异常类型。为了更轻松地仅更改需要更改的文档部分,块标签定义了可以独立继承的单独实体:
-
主体注释
:方法的主要文档注释称为主体注释。如果不提供主体注释,将继承超类型的完整主体注释。如果提供任何文本作为主体注释,则不会继承超类型主体注释的任何部分。
-
@param 注释
:每个
@param
注释根据参数名称独立继承。如果不为某个参数提供
@param
注释,则将继承超类型的
@param
注释。
-
@return 注释
:如果未指定
@return
注释,则继承超类型的
@return
注释。
-
@throws 注释
:有特殊的继承规则,将在下面讨论。
如果一个方法从超类和超接口都继承了文档注释,则使用接口的注释。
通常,对文档注释的更改只涉及添加额外信息。例如,一个重写方法可能保证它永远不会返回
null
,而父方法可能返回
null
。为了避免手动复制超类型的文档注释,可以使用
{@inheritDoc}
标签从超类型复制文档注释。
{@inheritDoc}
标签可以出现在主体注释中或任何块标签内,它会复制该实体的整个超类型的文档注释。例如,一个不再返回
null
的方法可以有如下文档注释:
/**
* @return {@inheritDoc}
* This implementation never returns null.
*/
{@inheritDoc}
标签允许在继承的文档之前或之后轻松添加新文档,但它的有效性取决于原始文档的编写方式。例如,如果前一个方法的原始
@return
注释是:
@return The value last set, or null if it has not been set.
那么添加的文档会导致描述不够清晰:
Returns: The value last set, or null if it has not been set.
This implementation never returns null.
为了清晰起见,重写整个文档注释可能比尝试扩充它更好。
4. 继承 @throws 注释
继承
@throws
注释有一个特殊规则:重写方法仅继承其
throws
子句中列出的、且被重写方法记录的异常的
@throws
注释。例如,如果原始方法有一个关于
IOException
的
@throws
注释,而重写方法声明它抛出
IOException
,则该注释将被继承。但是,如果重写方法声明它抛出
FileNotFoundException
(
IOException
的子类),则该注释不会被继承,因为该异常类型未被重写方法记录。对
@throws
注释继承时机的这种限制是必要的,因为自动继承
@throws
注释通常是错误的做法。不幸的是,不继承它们也可能是错误的做法。
重写方法可以抛出比被重写方法更少的受检查异常,但不能更多。因此,自动继承实际上不会抛出的受检查异常的
@throws
注释是错误的做法。对于受检查异常,只继承
throws
子句中列出的异常的文档注释是有意义的,毕竟这些是唯一可能抛出的受检查异常。所以,如果仍然抛出该异常,则继承注释;如果不抛出,则不继承注释。
运行时异常通常不会在
throws
子句中声明,这给情况增加了一些复杂性。通常希望继承像
IllegalArgumentException
这样的异常的
@throws
注释,因为对于重写的方法来说是非法的,对于重写后的方法通常也是非法的,所以如果不自动继承注释,该异常将不会被记录,这是错误的。但是,考虑一个接口,其中有可选实现的方法声明它们抛出
UnsupportedOperationException
,这个运行时异常由一个
@throws
注释记录。如果自动继承该注释,那么即使某个类的实现支持该操作,因此永远不会抛出该异常,该异常仍会被记录为被抛出,这同样是错误的。
通过要求在继承关联的
@throws
注释之前将异常列在
throws
子句中,可以避免继承不适用的
@throws
注释的问题。然而,这促进了一种将运行时异常列在方法的
throws
子句中的编程风格,这与标准做法相悖。建议继续只在方法的
throws
子句中列出受检查异常。对于未检查异常,建议手动重写
@throws
注释,但使用
{@inheritDoc}
来避免手动复制异常描述。例如,可以使用以下方式记录方法在其父方法会抛出
IllegalArgumentException
时仍然会抛出该异常:
@throws IllegalArgumentException {@inheritDoc}
仍然需要记住,未检查异常必须以这种方式手动记录。
总结
本文详细介绍了 Java 文档注释的结构、各种标签的使用以及方法文档注释的继承规则。通过合理使用文档注释和标签,可以提高代码的可读性和可维护性,方便开发者之间的交流和协作。在实际开发中,应根据具体情况选择合适的标签和注释方式,确保文档的准确性和清晰性。
表格总结
| 标签类型 | 标签名称 | 作用 |
|---|---|---|
| 块标签 | @see | 创建交叉引用链接到其他 javadoc 文档 |
| 块标签 | @deprecated | 标记标识符为已弃用 |
| 块标签 | @author | 指定类或接口的作者 |
| 块标签 | @version | 指定类或接口的版本规范 |
| 块标签 | @since | 指定实体添加到系统的版本 |
| 行内标签 | {@link} | 在注释文本中嵌入交叉引用链接 |
| 行内标签 | {@linkplain} | 与 {@link} 类似,但使用普通字体 |
| 行内标签 | {@literal} | 使文本按原样打印,不解释为 HTML |
| 行内标签 | {@code} | 以代码字体打印文本 |
| 行内标签 | {@value} | 替换为常量静态字段的实际值 |
| 行内标签 | {@docRoot} | 提供文档树中其他文件的相对引用 |
| 行内标签 | {@inheritDoc} | 从超类型复制文档注释 |
mermaid 流程图 - 方法文档注释继承流程
graph TD;
A[开始] --> B{是否有文档注释};
B -- 否 --> C[继承超类型文档注释];
B -- 是 --> D{是否有主体注释};
D -- 是 --> E[不继承主体注释];
D -- 否 --> F[继承主体注释];
G{是否有 @param 注释};
G -- 是 --> H[使用自身 @param 注释];
G -- 否 --> I[继承超类型 @param 注释];
J{是否有 @return 注释};
J -- 是 --> K[使用自身 @return 注释];
J -- 否 --> L[继承超类型 @return 注释];
M{是否有 @throws 注释且异常在 throws 子句中};
M -- 是 --> N[继承 @throws 注释];
M -- 否 --> O[不继承 @throws 注释];
C --> G;
E --> G;
F --> G;
H --> J;
I --> J;
K --> M;
L --> M;
N --> P[结束];
O --> P;
这个流程图展示了方法文档注释继承的主要流程,从判断是否有文档注释开始,逐步确定主体注释、
@param
注释、
@return
注释和
@throws
注释的继承情况。
Java文档注释的全面指南
5. 文档注释使用示例
为了更好地理解如何使用文档注释和各种标签,下面给出一个完整的 Java 类示例,展示如何对类、方法、字段等进行详细的文档注释:
/**
* This is a sample class demonstrating the use of Java doc comments.
*
* @author John Doe
* @version 1.0
* @since 1.0
*/
public class SampleClass {
/**
* The default value for the sample field.
*/
public static final int DEFAULT_VALUE = 10;
/**
* A sample field with a description.
*/
private int sampleField;
/**
* Constructs a new SampleClass object with the given initial value.
*
* @param initialValue The initial value for the sample field.
*/
public SampleClass(int initialValue) {
this.sampleField = initialValue;
}
/**
* Gets the current value of the sample field.
*
* @return The current value of the sample field.
*/
public int getSampleField() {
return sampleField;
}
/**
* Sets the value of the sample field.
*
* @param newValue The new value to set for the sample field.
* @throws IllegalArgumentException If the new value is negative.
*/
public void setSampleField(int newValue) throws IllegalArgumentException {
if (newValue < 0) {
throw new IllegalArgumentException("Value cannot be negative.");
}
this.sampleField = newValue;
}
/**
* Performs a sample operation and returns the result.
*
* @param input The input value for the operation.
* @return The result of the operation.
* @throws ArithmeticException If the input is zero.
* @see #getSampleField()
*/
public int performOperation(int input) throws ArithmeticException {
if (input == 0) {
throw new ArithmeticException("Input cannot be zero.");
}
return sampleField / input;
}
}
在这个示例中:
- 类
SampleClass
有一个整体的文档注释,包含了作者、版本和添加到系统的版本信息。
- 静态常量
DEFAULT_VALUE
有一个简单的描述性注释。
- 构造函数
SampleClass(int initialValue)
使用
@param
标签对参数进行了说明。
-
getSampleField()
方法使用
@return
标签说明了返回值。
-
setSampleField(int newValue)
方法使用
@param
标签说明参数,使用
@throws
标签说明了可能抛出的异常。
-
performOperation(int input)
方法综合使用了
@param
、
@return
、
@throws
和
@see
标签,提供了详细的文档信息。
6. 文档注释的最佳实践
为了使文档注释更加清晰、有用,以下是一些最佳实践建议:
1.
保持简洁明了
:文档注释的第一句应该是一个简洁的摘要,能够快速传达标识符的主要功能。后续的描述应该详细但不冗长,避免使用过于复杂的句子和术语。
2.
使用完整的句子
:虽然文档注释可以使用简洁的语言,但尽量使用完整的句子,以提高可读性。
3.
一致性
:在整个项目中保持文档注释的风格和格式一致。例如,使用相同的标签顺序、注释格式等。
4.
及时更新
:当代码发生变化时,及时更新相应的文档注释,确保文档与代码保持一致。
5.
避免重复
:如果多个方法或类有相似的功能,可以使用继承和
{@inheritDoc}
标签来避免重复编写文档注释。
6.
详细记录异常
:使用
@throws
标签详细记录方法可能抛出的异常,包括异常的类型和触发条件。
7.
使用标签
:合理使用各种标签,如
@see
、
@param
、
@return
等,提供丰富的信息。
7. 文档注释的工具支持
javadoc
是 Java 提供的一个强大的工具,用于从源文件中的文档注释生成 HTML 格式的文档。以下是使用
javadoc
工具的基本步骤:
1.
编写文档注释
:在 Java 源文件中按照规范编写文档注释。
2.
打开命令行
:进入包含 Java 源文件的目录。
3.
运行
javadoc
命令
:
- 生成单个文件的文档:
plaintext
javadoc YourClass.java
- 生成整个包的文档:
plaintext
javadoc -d doc com.yourpackage
其中,
-d
选项指定生成文档的输出目录,
com.yourpackage
是要生成文档的包名。
4.
查看生成的文档
:打开生成的 HTML 文件,通常位于指定的输出目录中。
表格总结 - 最佳实践
| 最佳实践 | 说明 |
|---|---|
| 保持简洁明了 | 第一句为简洁摘要,后续描述详细不冗长 |
| 使用完整的句子 | 提高可读性 |
| 一致性 | 项目中保持风格和格式一致 |
| 及时更新 | 代码变化时同步更新文档注释 |
| 避免重复 |
使用继承和
{@inheritDoc}
标签
|
| 详细记录异常 |
使用
@throws
标签说明异常类型和触发条件
|
| 使用标签 | 合理运用各种标签提供丰富信息 |
mermaid 流程图 - 使用 javadoc 工具流程
graph TD;
A[编写文档注释] --> B[打开命令行];
B --> C{选择生成方式};
C -- 单个文件 --> D[javadoc YourClass.java];
C -- 整个包 --> E[javadoc -d doc com.yourpackage];
D --> F[生成文档];
E --> F;
F --> G[查看生成的 HTML 文件];
这个流程图展示了使用
javadoc
工具生成文档的主要流程,从编写文档注释开始,经过命令行操作,最终生成并查看文档。
总结
Java 文档注释是提高代码可读性和可维护性的重要工具。通过合理使用各种标签和遵循最佳实践,可以为代码提供详细、准确的文档。同时,利用
javadoc
工具可以方便地将文档注释转换为 HTML 格式的文档,便于开发者之间的交流和协作。在实际开发中,应该养成编写良好文档注释的习惯,为项目的长期发展奠定基础。
超级会员免费看
1340

被折叠的 条评论
为什么被折叠?



