4. 注释编写规范¶
为你的类和方法编写文档
始终清楚地为你的代码编写文档是很重要的。对于 Java 程序员来说,一个名为 javadoc 的工具(Java API 文档生成器)建立了一些通用的注释规范。这个工具可以从源代码中自动提取文档注释,并生成 HTML 类的描述,就像 Sofia API 中的那些一样。这个工具如此流行、如此常用,以至于它已经为人们如何记录 Java 代码中的外部可见特性设定了标准。(参见 How to Write Doc Comments for the Javadoc Tool 一文。)
4.1. JavaDoc 注释¶
javadoc 工具期望注释以某种特定方式编写——其他注释都会被忽略。JavaDoc 注释(也简称为 “doc 注释”)总是以 /** 开头,并以 */ 结尾。在为你的代码生成文档时,任何其他注释都会被忽略。此外,描述某样东西的 JavaDoc 注释总是立即出现在它所描述的对象之前。
在 JavaDoc 注释内部,可以嵌入特殊的标签来指示特定种类的信息。这些文档标签可以从你的源代码自动生成完整、格式良好的 API 文档。所有 JavaDoc 标签都以 at 符号( @ )开头。
如果你已经了解一些 HTML,你甚至可以在 JavaDoc 注释中嵌入简单的 HTML 标记,它会出现在为你的类生成的文档中。如果你想在类的描述中添加项目符号列表,或者想让注释的某一部分以粗体突出显示等等,这会非常方便。
4.2. 描述类¶
你应该在每个类声明的开头之前紧邻放置一段描述性的 JavaDoc 注释:
/**
* Write a one-sentence summary of your class here.
* Follow it with additional details about its purpose, what abstraction
* it represents, and how to use it.
*
* @author Stephen Edwards (stedwar2)
* @version 2011.01.30
*/
public class UserProfile
. . .
{
. . .
}
类说明通常使用两个标签: @author 表示谁编写了这个文件, @version 表示这个文件或项目的“版本”。你可以在 @author 标签中使用你的全名,或只使用 PID。在本课程中,用文件编写日期作为 @version 标签中的版本信息也是可以的。
使用 @author 和 @version 等标签时,请确保把它们放在文档注释内每行的开头。
在你的代码中,如果代码是与同伴合作编写的,你可以为每一位同伴提供单独的 @author 行——务必同时列出你的用户名(PID)以及姓名。此外,如果你最初使用的是 BlueJ 生成的注释(如上例所示),别忘了把注释内部的文本替换成你自己的。 javadoc 工具会把你注释中的第一句话用作你的类的单句摘要,并把注释的完整文本用作类的完整描述。
请记住,如果只编写普通注释,将不会被识别为用于文档生成的“正式”描述文本:
// This comment describes what this class does, but because it
// uses //, it won't be recognized as a JavaDoc comment.
public class UserProfile
. . .
{
. . .
}
4.3. 为方法编写文档注释¶
你应该在你编写的每个方法或构造函数的声明之前紧邻放置一段描述性的 JavaDoc 注释:
/**
* Move the robot forward to the next HTML heading.
*/
public void advanceToNextHeading()
{
. . .
}
与其他 JavaDoc 注释一样,请确保这段注释紧邻在它所描述的方法之前出现。对于带参数的方法,你还应该为每个参数的含义提供简要描述。例如,我们可能有一个 UserProfile 类为它的 name 提供一个 setter 方法:
/**
* Set the profile's name to the given value.
*
* @param newName The new name for this profile.
*/
public void setName(String newName)
{
. . .
}
这里,使用了 @param 标签来描述参数的含义和用法。为方法(或构造函数)中的每个参数使用一个单独的 @param 标签。确保这些标签从注释行的开头开始,并把所有同名的标签放在一起(也就是说,所有 @param 标签应彼此相邻)。
同样, javadoc 会把你注释中的第一句话用作方法功能的单句摘要。注释的其余部分将用于生成方法的完整描述。
有些方法有返回值——也就是说,它们会把信息返回给调用者。例如, getName() 方法可能返回一个包含用户档案当前名字的 String。你可以使用 @return 标签记录返回的是什么样的信息:
/**
* Get this profile's name.
*
* @return This profile's name
*/
public String getName()
{
. . .
}
4.4. 生成你的文档¶
4.4.1. 使用 Eclipse¶
可以使用 Generate Javadoc 向导在 Eclipse 中为项目创建 Javadoc:
从 Project 菜单中选择 Generate Javadoc…
指定
javadoc程序在你电脑上的位置。通常,它位于 JAVA_HOME 的 bin 目录下。例如,在 Windows 平台上为C:\Program Files\Java\jdk1.11.0_21\bin\javadoc.exe,在 MacOS 中为/Library/Java/JavaVirtualMachines/jdk1.8.0_112.jdk/Contents/Home/bin/javadoc。选择要为其生成 Javadoc 的项目和包。
缩小将生成 Javadoc 的源文件的范围(默认情况下会选中所有文件)。
通过选择可见性(访问修饰符)来限制将生成 Javadoc 的类成员。例如:如果选择 Public,则只有 public 方法会生成 Javadoc。如果选择 Protected,则只有 protected 和 public 方法会生成 Javadoc,依此类推。
指定 Javadoc 将存放到的目标目录。
点击 Next。
选择 Javadoc 生成所需的任何选项。
在这里,你可以指定文档标题(1);文档结构(2);文档标签(3);为其生成引用链接的 JAR 文件和项目(4);以及文档的样式表(5):
点击 Finish
你的 Javadoc 将位于你在步骤 6 中指定的文件夹内,你可以用浏览器打开它们。
4.4.2. 使用 BlueJ¶
如果你使用 BlueJ,可以使用 “Tools->Project Documentation” 命令直接从源代码为你的项目生成完整文档。这可能需要一分钟,但完成后会打开一个新的浏览器窗口,显示为你的类生成的所有文档。它将与 Student Library API 类似,但针对的是你自己的代码。
此外,在编辑单个文件时,你会注意到编辑窗口右上角有一个下拉列表。这个列表给你两个选择:“Implementation”,它显示你通常编辑的代码;以及 “Interface”,它改而显示当前类的生成文档视图。
在 BlueJ 中使用这两种方式,你可以查看你的注释在生成的文档中的效果。
4.5. 代码中的其他注释¶
JavaDoc 注释是你的类的外部可访问功能的 “公开” 文档。通常,你可能还希望包含 “内部”(即私有)的文档,它只对直接阅读源代码的人有用。任何不以 /** 开头的注释都被视为私有的,仅供有权访问源代码的人使用。你可以在任何你喜欢的地方自由使用这类注释来提高代码的可读性, 但是……
4.6. 内部注释是万不得已的文档技巧¶
仔细选择所有名称,使一个天真(naïve)的读者第一眼的解读总是正确的。不要选择那些可能让人误解方法的用途或变量所含信息的名称。选择糟糕的名称或迂回复杂的逻辑结构,然后试图用冗长的注释来解释它们,对提高可读性几乎无济于事。这对方法来说更是如此,因为一半的情况下,读者看到你的方法名是在它被调用的地方,而不是在阅读方法本身的时候。如果方法应该做什么并不立即清楚,这会影响所有调用该方法的代码的可读性,无论你在方法本身中放了多少注释。
努力编写清晰易懂的代码,仅凭你选择的名称和你使用的结构就能让人理解。如果你觉得必须添加内部注释来解释某事,问问自己什么需要解释。如果你需要解释某个名称指的是什么或你打算如何使用它,考虑选择一个更好的名称。如果你不得不解释一系列复杂的 if 语句或其他某种迂回复杂的结构,问问自己(或助教)是否有更好的方法。只有在考虑过这些替代方案之后,才应该添加描述性注释。
4.7. 多余注释比没有注释更糟¶
考虑这些注释:
user = new UserProfile(); // Create a new user profile
x = x + 1; // Add one to x
user.setName("Ben"); // change the profile name
这些都是无用注释的例子。许多学生给代码添加注释只是为了“确保一切都记录在案”,或者因为他们认为大量注释正是老师想要的。然而,这样的注释只会妨碍阅读代码。只有在注释 能表达代码本身尚未体现的信息 时,才应该添加它们。注释是可怜的读者必须费力浏览的额外信息,所以你需要仔细权衡它们的收益与阅读它们的成本。这个读者可能是——而且常常是——你自己,所以一个好的思维模式是:把你正在写的注释看作写给未来自己的消息。未来的你编程经验会比现在的你更丰富,但会忘记甚至一周前所写代码的细节。你应该以尽量减少这个未来的你为理解和维护你的代码所必须付出的脑力劳动为目标来编写注释。
