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 文檔標記總表:

Tag Introduced 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 ----


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM