文档注释

JDK 包含一个很有用的工具, 叫做 javadoc, 它可以由源文件生成一个 HTML 文档。 事 实上, 在第 3 章讲述的联机 API 文档就是通过对标准 Java 类库的源代码运行 javadoc 生 成的。

如果在源代码中添加以专用的定界符 /** 开始的注释, 那么可以很容易地生成一个看上 去具有专业水准的文档。这是一种很好的方式, 因为这种方式可以将代码与注释保存在一个 地方。如果将文档存人一个独立的文件中, 就有可能会随着时间的推移, 出现代码和注释不 一致的问题。 然而, 由于文档注释与源代码在同一个文件中, 在修改源代码的同时, 重新运 行 javadoc 就可以轻而易举地保持两者的一致性。

 

注释的插入

javadoc 实用程序(utility) 从下面几个特性中抽取信息:

•包 •公有类与接口

•公有的和受保护的构造器及方法 •公有的和受保护的域
在第 5 章中将介绍受保护特性, 在第 6 章将介绍接口。

应该为上面几部分编写注释 、 注释应该放置在所描述特性的前面。 注释以 /** 开始, 并 以 */ 结束。

每个 /** . . . */ 文档注释在标记之后紧跟着自由格式文本 ( free-form text )。 标记由 @ 开 始, 如 @author 或 @param。

自由格式文本的第一句应该是一个概要性的句子。javadoc 实用程序自动地将这些句子抽 取出来形成概要页。

在自由格式文本中, 可以使用 HTML 修饰符, 例如, 用于强调的 <em>...</eitf>、用于 着重强调的 <strong>...</stroiig> 以及包含图像的 <img ..•> 等。不过, 一定不要使用 <hl> 或 <hr>, 因为它们会与文档的格式产生冲突。若要键入等宽代码,需使用{@code...}而不是 <code>...</code> 这样一来, 就不用操心对代码中的 < 字符转义了。

释 如果文档中有到其他文件的链接 例如 图像文件(用户界面的组件的图表或图 :,,

像等), 就应该将这些文件放到子目录 doc-files 中。javadoc 实用程序将从源目录拷贝这

些目录及其中的文件到文档目录中。在链接中需要使用 doc-files 目录, 例如: <img src= “ doc-files/uml_png” alt=“ UML diagram” >。

 

类注释
类注释必须放在 import 语句之后, 类定义之前。

下面是一个类注释的例子:

/**

* A {©code Card} object represents a playing card, such
* as "Queen of Hearts". A card has a suit (Diamond, Heart,
* Spade or Club) and a value (1 = Ace, 2 . . . 10, 11 = Jack, * 12 = Queen, 13 = King)
V

public class Card

 

 

注释: 没有必要在每一行的开始用星号 *, 例 如, 以下注释同样是合法的:

/**

A <code>Card</code> object represents a playing card, such as "Queen of Hearts". A card has a suit (Diamond, Heart , Spade or Club) and a value (1 = Ace, 2 . . . 10, 11 = jack, 12 = Queen, 13 = King).

V

然而, 大部分 IDE 提供了自动添加星号 *, 并且当注释行改变时, 自动重新排列这 些星号的功能。

 

 

方法注释

每一个方法注释必须放在所描述的方法之前。 除了通用标记之外, 还可以使用下面的标记: •@param 变量描述

这个标记将对当前方法的“ param” (参数)部分添加一个条目。这个描述可以占据多

行, 并可以使用 HTML 标记。一个方法的所有 @param 标记必须放在一起。 • @return 描述

这个标记将对当前方法添加“ return” (返回)部分。这个描述可以跨越多行, 并可以

使用 HTML 标记。 • ©throws 类描述

这个标记将添加一个注释, 用于表

 

 

域注释

只需要对公有域 (通常指的是静态常量)建立文档。 例如 ,

/**

* The "Hearts" card suit

V
public static final int HEARTS = 1;

 

通用注释

下面的标记可以用在类文档的注释中。 •eauthor 姓名

这个标记将产生一个 ** author" ( 作者)条目。可以使用多个 @aUthor 标记, 每个 @

author 标记对应一个作者 參 ©version

这个标记将产生一个“ version ”(版本)条目。 这里的文本可以是对当前版本的任何描

述。

下面的标记可以用于所有的文档注释中。 •@sinee文本

这个标记将产生一个“ since” (始于)条目。这里的 text 可以是对引人特性的版本描 述 例如 ©since version 1.7.10

•。, @deprecated

这个标记将对类、方法或变量添加一个不再使用的注释。 文本中给出了取代的建议。 例如,

@deprecated Use <code> setVIsible(true) </code> instead

通过 @see 和 @link 标记, 可以使用超级链接, 链接到 javadoc 文档的相关部分或外

部文档。 •®see引用

这个标记将在“ see also” 部分增加一个超级链接。它可以用于类中, 也可以用于方 法中。 这里的引用可以选择下列情形之一:

package, class眷feature label <a href=" ..n>hbek/a>

• ntextn

第一种情况是最常见的。 只要提供类、方法或变量的名字,javadoc 就在文档中插入 一个超链接。 例如,
@see com.horstraann.corejava.Employee#raiseSalary(double)

建立一个链接到 com.horstmann.corejava.Employee 类的 raiseSalary(double) 方法的超 链接。 可以省略包名,

 

甚至把包名和类名都省去, 此时, 链接将定位于当前包或当前类

需要注意, 一定要使用井号(#,) 而不要使用句号(.)分隔类名与方法名, 或类 名与变量名。Java 编译器本身可以熟练地断定句点在分隔包、 子包、类、内部类与方 法和变量时的不同含义。 但是 javadoc 实用程序就没有这么聪明了, 因此必须对它提 供帮助。

如果 @see 标记后面有一个 < 字符, 就需要指定一个超链接。 可以超链接到任何 URL。 例如:

@see <a href="m«w.horstmann.com/corejava.htinl">The Core ]ava home page</a>

在上述各种情况下, 都可以指定一个可选的标签(label) 作为链接锚(link anchor) o 如果省略了 label , 用户看到的锚的名称就是目标代码名或 URL。

如果 @see 标记后面有一个双引号(")字符, 文本就会显示在 “ see also” 部分。 例如,

Isee "Core Java 2 volume 2n

可以为一个特性添加多个 @see 标记, 但必须将它们放在一起。
•如果愿意的话, 还可以在注释中的任何位置放置指向其他类或方法的超级链接, 以及

插人一个专用的标记, 例如,

{@link package,classifeaturelabel] 这里的特性描述规则与 @see 标记规则一样。

4.9.6 包与概述注释

可以直接将类、方法和变量的注释放置在 Java 源文件中, 只要用 /** . . . */ 文档注释界 定就可以了。但是,要想产生包注释, 就需要在每一个包目录中添加一个单独的文件。可以 有如下两个选择:

1 ) 提供一个以 package.html 命名的 HTML 文件。在标记 <body>—</body> 之间的所有 文本都会被抽取出来。

2 ) 提供一个以 package-info.java 命名的 Java 文件。 这个文件必须包含一个初始的以 /** 和 */ 界定的 Javadoc 注释, 跟随在一个包语句之后。它不应该包含更多的代码或注释。

还可以为所有的源文件提供一个概述性的注释。 这个注释将被放置在一个名为 overview, html 的文件中, 这个文件位于包含所有源文件的父目录中。标记 <body>... </body> 2间的所 有文本将被抽取出来。 当用户从导航栏中选择“ Overview ” 时, 就会显示出这些注释内容。

4.9.7 注释的抽取

这里, 假设 HTML 文件将被存放在目录 docDirectory 下。 执行以下步骤:

1 ) 切换到包含想要生成文档的源文件目录。 如果有嵌套的包要生成文档, 例如 com. horstmann.corejava, 就必须切换到包含子目录com的目录(如果存在overview.html文件的 话, 这也是它的所在目录 )。

 

2 ) 如果是一个包, 应该运行命令:

javadoc -d docDirectory nameOfPackage 或对于多个包生成文档, 运行 :
javadoc -d docDirectory nameOfPackage\ nameOfPackage . . . 如果文件在默认包中, 就应该运行:
javadoc -d docDirectory *.java

 

如果省略了 -d docDirectory 选项, 那 HTML 文件就会被提取到当前目录下。 这样有可能 会带来混乱, 因此不提倡这种做法。

可以使用多种形式的命令行选项对 javadoc 程序进行调整。 例如, 可以使用 -author 和

-version 选项在文档中包含 @author 和 @version 标记 (默认情况下, 这些标记会被省 略)。另一个很有用的选项是-link, 用来为标准类添加超链接。例如,如果使用命令

javadoc -link http://docs.oracle.eom/:javase/8/docs/api *.java

那么, 所有的标准类库类都会自动地链接到 Oracle 网站的文档。
如果使用 -linksource 选项, 则每个源文件被转换为 HTML ( 不对代码着色, 但包含行编

号 ,) 并且每个类和方法名将转变为指向源代码的超链接。
有关其他的选项, 请查阅 javadoc 实用程序的联机文档, http://docs.orade.eom/javase /8/

docs/guides/javadoc 0

注释: 如果需要进一步的定制, 例如, 生成非 HTML 格式的文档, 可以提供自定义的 doclet, 以便生成想要的任何输出形式。显然, 这是一种特殊的需求, 有关细节内容请查 阅 http://docs.oracle.com/javase/8/docs/guides/javadoc/doclet/overview.html 的联机文档。

 

1. 一定要保证数据私有

这是最重要的; 绝对不要破坏封装性。有时候, 需要编写一个访问器方法或更改器方法, 但是最好还是保持实例域的私有性。很多惨痛的经验告诉我们, 数据的表示形式很可能会改 变, 但它们的使用方式却不会经常发生变化。当数据保持私有时, 它们的表示形式的变化不 会对类的使用者产生影响, 即使出现 bug 也易于检测。

2. 一定要对数据初始化

Java 不对局部变量进行初始化, 但是会对对象的实例域进行初始化。 最好不要依赖于系 统的默认值, 而是应该显式地初始化所有的数据, 具体的初始化方式可以是提供默认值, 也 可以是在所有构造器中设置默认值。

 

3. 不要在类中使用过多的基本类型

就是说, 用其他的类代替多个相关的基本类型的使用。这样会使类更加易于理解且易于 修改。例如, 用一个称为 Address 的新的类替换一个 Customer 类中以下的实例域:

private String street; private String city; private String state; private int zip;

 

这样, 可以很容易处理地址的变化, 例如, 需要增加对国际地址的处理。
4. 不是所有的域都需要独立的域访问器和域更改器
或许, 需要获得或设置雇员的薪金。 而一旦构造了雇员对象, 就应该禁止更改雇用日

期, 并且在对象中, 常常包含一些不希望别人获得或设置的实例域, 例如, 在 Address 类中, 存放州缩写的数组。

 

5. 将职责过多的类进行分解

这样说似乎有点含糊不清, 究竟多少算是“ 过多” ? 每个人的看法不同。但是, 如果明 显地可以将一个复杂的类分解成两个更为简单的类, 就应该将其分解(但另一方面, 也不要 走极端。 设计 10 个类, 每个类只有一个方法, 显然有些矫枉过正了)。

下面是一个反面的设计示例。

public class CardDeck // bad design {

private int 口 value; private int[] suit;

public CardDeck() { . . . }
public void shuffle0 {•••} public int getTopValueO { . . . } public int getTopSuitO { . . . }

.}

实际上, 这个类实现了两个独立的概念: 一副牌(含有 shuffle 方法和 draw 方法)和一 张牌(含有查看面值和花色的方法)。另外,引入一个表示单张牌的 Card类。现在有两个类, 每个类完成自己的职责:

public class CardDeck

{
private Card[] cards;

public CardDeckO { • . . } public void shuffle() { . . . } public Card getTopO { . . . } public void draw() { . . . }

}

public class Card {

private int value; private int suit;

public void drawO {• }

第4章?象与? 145

146 Java核心技?

public Card(int aValue, int aSuit) { . . . } public int getValueO { . . . }
public int getSuitO { . . . }

}

6. 类名和方法名要能够体现它们的职责

与变量应该有一个能够反映其含义的名字一样, 类也应该如此(在标准类库中, 也存在 着一些含义不明确的例子, 如: Date 类实际上是一个用于描述时间的类 )。

命名类名的良好习惯是采用一个名词(Order)、 前面有形容词修饰的名词( RushOrder) 或动名词(有“ -ing”后缀)修饰名词(例如,BillingAddress)。对于方法来说,习惯是访问 器方法用小写 get 开头 ( getSalary ), 更改器方法用小写的 set 开头(setSalary )

7. 优先使用不可变的类 —

LocalDate 类以及 java.time 包中的其他类是不可变的 没有方法能修改对象的状态。 类似 plusDays 的方法并不是更改对象, 而是返回状态已修改的新对象。

更改对象的问题在于, 如果多个线程试图同时更新一个对象, 就会发生并发更改。其结 果是不可预料的。 如果类是不可变的, 就可以安全地在多个线程间共享其对象。

因此, 要尽可能让类是不可变的, 这是一个很好的想法。对于表示值的类, 如一个字符 串或一个时间点, 这尤其容易。 计算会生成新值, 而不是更新原来的值。

当然, 并不是所有类都应当是不可变的。如果员工加薪时让 raiseSalary 方法返回一个新 的 Employee 对象, 这会很奇怪。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值