• javadoc


    作为一个 Java 程序员,Javadoc 大家都应该写过吧,是不是觉得写的时候特简单呢?相信看完本文后你会若有所思。另外,本文非常适合处女座程序员阅读。

    句号

    为什么是句号而不是其他的标点符号呢?因为这涉及到一个 JDK 文档生成的规则:

    The first sentence of each doc comment should be a summary sentence, containing a concise but complete description of the API item. This means the first sentence of each member, class, interface or package description. (成员、类、接口或包注释的第一个句子将作为该注释项的总结,这个句子应该是言简意赅的)

    既然提到了句子,那就说明应该用标准的方式——句号来进行第一个句子的断句识别。也许是为了简洁,Javadoc 工具并没有“多语言句号识别”这个特性,所以不管我们用什么语言撰写文档注释,断句符号都必须是英文状态下的句号——.

    比如在 NetBeans IDE 里(默认编辑器配置)可以很直观的看到用于总结的第一个句子和后面描述的区别:

    first-sentence

    在生成 Javadoc 后,类概要页面我们可以看到最终的效果:

    class-summery

    在使用中文撰写文档注释时,为了保持整体风格一致,在所有需要使用句号的地方有两种策略可选择:

    • 都使用英文句号:这样做可以让生成的文档句号统一,但缺点是看上去有点别扭
    • 只有第一个句子使用英文句号,其余地方都是要中文句号:这样做后生成的文档看上去比较顺眼,但别人可能会奇怪为什么第一个句号是 .

    当然,最彻底的解决方案是不用中文写文档注释,这样就不存在要统一的问题了!

    下面我们重点介绍各种你熟悉的或是不熟悉的 Javadoc 文档标记(它们很有内涵)

    @author

    该标记使用频率是所有文档标记中最高的,我想这是因为:

    • 做好事要留名
    • 使用超简单,就像在填表格(姓名:           )一样自然

    来看看大牛怎么写的:

    commons-lang-stringutils

    (from Commons Lang 2.5 StringUtils)

    总结下来有三种写法:

    • 纯文本
    • 带邮箱链接
    • 带 HTTP 链接

    (个人建议用 HTTP 链接:打码时可以顺便推广一下自己的博客,哈哈)

    另外,在 JDK 代码中我们经常看到 @author unascribed,意思是:“该代码第一原作者不是我,但我实在也不知道是谁,就记作无名氏吧”(这是多么严肃的一种版权意识啊)

    @serialXXX

    这个系列应该是最不常用的文档标记了,它们到底是干嘛用的呢?请看这里

    (我一次也没有使用过这些文档标记,看了官方文档后也还是没有搞懂怎么用,求各位指教)

    @value

    这个文档标记非常实用(不光好用),可以用于生成被标记的常量字段的值。

    直接用于常量字段时:

    value-code

    value-html

    也可以使用引用方式:

    value-ref-code

    value-ref-html 

    {@inheritDoc}

     这个标签体现了 Java 面向对象的精辟所在:不但可以类可以集成,连文档都可以继承(足见 Java 在经典面向对象概念上的完备与圆润)。

    比如有个计算面积的接口:

    inheritdoc-interface-code

    它的实现方法标注了 {@inheritDoc}(处女座阅读提示:无 .)

    inheritdoc-impl-code

    最后生成的文档:

    inheritdoc-html

    • 基类的文档注释被继承到了子类
    • 子类可以再加入自己的注释(特殊化扩展)
    • @return @param @throws 也会被继承

    其实在不写 {@inheritDoc} 的情况下也存在文档注释的继承,具体规则请看这里

    {@link} {@linkplain}

    这两个链接标记大家用/见的应该比较多,但它们有什么区别、在什么场景下该怎么使用很少有人能够区分开(我猜你要用的时候一般也都是用 link 吧)。

    看看官网的标准解释:

    link


    link 和 linkplain 的实参都是 package.class#member label 。唯一的不同就是因为字体不同,如果 label 是个纯文本,那就使用 linkplain 吧。(根据这点,我严重怀疑 Javadoc 文档标记的设计者是处女座,~ ~)

    pre

    没错,这就是那个 HTML 标签,用于显示“原始样子”的。这个标签在写 Javadoc 的时候非常有用,用或者不使用在打码的时候看上去差别不大:

     pre-code

    但最终生成 apidocs 之后差别一目了然(处女座阅读提示:在源码文档注释中特别需要注意 pre 后 { 的位置,紧跟 *,无空格)

    pre-html

    @since

    这个从字面的意思上很好理解,所以使用的比较多(如同 @author、@version 一样)。但问题是大家写的时候表达的意思五花八门,常见的有:

    1. 想表达日期/时间
      @since 2014-01-01
      @since 2014-01-01 14:00:00
    2. 想表达可运行的 JDK 版本
      @since JDK1.5
    3. 想表达加入这个元素的版本
      @since 1.0.0

    根据官方文档解释,@since 表达的是被标记元素是哪个发布版本引入的(3)。比如别人在我们的文档注释中看到

    since

    那他可以(应该)认为这个类是在该程序对外发布 1.0.0 版本时已经引入的。如果他要做二次开发,那他就可以很清晰的向后兼容了(我们在用 JDK 的时候就是这个场景)。

    @version

    提到了 @since 就自然会联想到 @version,因为它们的实参都是版本相关的。@version 要表达的是被标记元素自己的版本(注意对比 @since),也就是说这个版本只要代码改过就应该发生变化,而 @since 是不会变的。

    官方文档也解释了怎么用好这个文档标记:通过 SCCS 字符 "%I%, %G%",例如 1.39, 02/28/97(文件版本号, 日期)生成。但实际上很少有项目这么做(至少目前 Oracle JDK 没这么做,甚至都没有使用 @version,或者是使用了但最后由于特殊原因总体移除了),大家一般都是 @version 1.0.0 然后就再也不修改了,不管被标记的元素改了多少次(这样的做法还不如不写)。

    当然,通过版本控制系统 hook 来做是比较经典的做法,不过这样总感觉没有把这个标记的能力完全发挥出来。在我们的项目里是这样使用的:@version 1.2.3.4, Jun 9, 2014

    重点是版本号部分,在这个例子中从左到右(1.2.3.4)分别表示:

    • 兼容性位 1,表示兼容性,如果 +1 了说明这个修改是不兼容的
    • 特性位 2,表示已引入了两个特性,每次 +1 说明引入一个新特性
    • 缺陷修复位 3,表示已经修复了 3 个缺陷,每次 +1 说明修复了一个缺陷
    • 重构位 4,表示已经进行了 4 次重构,每次 +1 说明重构了一次

    前面 3 位表达的意义和 Semantic Versioning 建议的一致,重构我觉得非常重要,所以也加了进来。

    @exception @throws

    这两兄弟的情况比 @link @linkplain 更纠结(人家 link 兄弟最起码可以区分出来使用场景)。按照官方文档解释:它们完全是同义词,没有任何区分。那当年 Sun 在 JDK1.2 的时候为什么要加入 @throws 呢——答案是起名失误了,词性没弄匹配:@throws Exception 比 @exception Exception 更符合语法,代入感更好!(细节:In javadoc, what is the difference between the tags @throws and @exception?

    标记总表

    来张 Javadoc 文档标记总表:

    TagIntroduced in JDK/SDK
    @author 1.0
    {@code} 1.5
    {@docRoot} 1.3
    @deprecated 1.0
    @exception 1.0
    {@inheritDoc} 1.4
    {@link} 1.2
    {@linkplain} 1.4
    {@literal} 1.5
    @param 1.0
    @return 1.0
    @see 1.0
    @serial 1.2
    @serialData 1.2
    @serialField 1.2
    @since 1.1
    @throws 1.2
    {@value} 1.4
    @version 1.0

    这个表是 JDK7 技术手册里的,从中我们可以看出,自 JDK1.5 以后就没有加过新的文档标记了,目测有两个原因:

    • Oracle:“这些已经足够开发人员使用了,没必要加新的了”
    • *Sun:“看吧,Oracle 严重缺乏折腾精神,当初不应该卖给它的”

    文档标记介绍完了,下面我们来聊聊 Javadoc 相关的其他侃点。

    getter/setter/isTrue

    对于 POJO 来说,这几个方法的注释格式非常固定,一般我们都是用 IDE 自动生成:这样的话别人一看到这样固定格式的注释(或者索性不要添加任何注释)就知道这部分相对于其他部分并不重要,而一旦有的 getter/setter/isTrue 注释不是这样约定的,那就说明了实现上面不只是简单的 get/set/is,还加入了额外的逻辑处理。

    对齐

    Javadoc 文档注释也有对齐(不是前面 pre 例子那种),这里说的对齐主要指的是以源码视图看到的,最典型的场景就是在给方法添加文档注释的时候,我们经常看到两种风格:

    align-para

    第一眼看上去是不是风格 2 要顺眼得多?但最好还是使用风格 1,因为:

    • 这和编辑器配置的字体有关,如果不是(适合的)等宽字体,那会非常的参差不齐
    • 浪费空间,特别是当注释内容多了需要换行的时候会很别扭
    • 最后生成的 apidocs 效果是一模一样的(无对齐)

    (一些 IDE 默认格式化文档注释的时候也是使用风格 1 进行格式化的,强烈建议使用风格 1)

    包注释

    和前面几点打码风格相关的细节比起来,包注释是具有一定的实用性的。虽然大家可能用得很少,但看得应该比较多,就是这部分:

    package

    这里我们使用了两种方式来生成包文档:

    • package.html:这是 JDK1.5 以前的方式,现在已经不推荐使用
    • package-info.java:目前推荐方式,因为这样可以使用注解

    在包上面使用注解?这个用法和在其他地方使用注解一样,只是被标注的元素变成了包,在运行时可以获取到包的注解,然后做你想做的事情吧!

    中文

    一开始我们提到了句号的问题(那的确是一个问题),最后我们来看看中文在写文档注释的时候也非常值得注意的一点(其实不只是 Javadoc 文档注释,该建议也适用于其他一些情况):在中文和英文、数字中间插入一个空格(本文就是这样排版的)。

    比如说:

    • 我觉得Java非常cool,特别是JDK8中的lambda,真希望9能带来更多实用特性
    • 我觉得 Java 非常 cool,特别是 JDK8 中的 lambda,真希望 9 能带来更多实用特性

    后者看上去就比前者更舒服一些,这样的排版方式适合纯文本编辑器,如果使用的是 Office 之类的工具就不需要手动空格了,因为它们默认已经处理的很好了。

    总结

    本文介绍了一些 Javadoc 文档注释相关的细节,从这冰山一角相信你对 Java 也有了另一番体验(Java 的进化、工业化)。

    总结一下本文内容:

    • 对于文档标记,大家可以尽量尝试使用:把自己的思想通过适合的方式表达给他人是一种好习惯
    • 对于风格相关,大家也可以适当尝试(处女座/强迫症就算了):某大厂在某次改句号问题后出现过生产故障

    不过,大家也千万不要太较真,毕竟对于一个好的程序来说,代码应该就是它的文档(之一)。

    参考

    ---- EOF ----
  • 相关阅读:
    技术周刊 · 耿耿星河欲曙天 | SpaceX 上的前端架构;跨平台新选择;开源世界的新“大门”;用户推荐算法的敲门砖……
    说说SVG的feTurbulence滤镜
    机器学习进阶
    小程序与动画的故事
    技术周刊 · 迢迢山径峻 | Web 开发成长图谱;下一代前端构建技术;AI 应用下支离破碎的真实;不懂产品不会开发;虚拟货币是新时代的黄金
    从中断机制看 React Fiber 技术
    三分钟了解数字人民币
    凹凸技术揭秘:如何服务 toG 项目——数字人民币项目前端总结
    使用 Phaser3+Matter.js 实现“合成大西瓜”游戏
    痞子衡嵌入式:快速定位i.MXRT600板级设计ISP[2:0]启动模式引脚上电时序问题的方法
  • 原文地址:https://www.cnblogs.com/KingIceMou/p/7169744.html
Copyright © 2020-2023  润新知