閱讀經(jīng)典——《Effective Java》09
要想使一個API真正可用,就必須為其編寫文檔。Java提供了Javadoc工具,使得為API編寫文檔變得非常容易。Javadoc利用特殊格式的文檔注釋,根據(jù)源代碼自動生成API文檔。
- 通用規(guī)則
- 案例說明
- 更多用法
通用規(guī)則
- 必須在每個被導出的類、接口、構造器、方法和域聲明之前增加一個文檔注釋。如果類是可序列化的,也應該對它的序列號形式編寫文檔。
-
方法的文檔注釋應該簡潔地描述出它和客戶端之間的約定。這個約定應該說明這個方法做了什么,而不是說明它是如何做的。文檔注釋應該列舉出這個方法的所有前提條件和后置條件。所謂前提條件是指為了使客戶能夠調(diào)用這個方法而必須要滿足的條件;所謂后置條件是指在調(diào)用成功完成之后,哪些條件必須要滿足。一般情況下,前提條件由
@throws
標簽描述隱含的異常,也可以在一些受影響參數(shù)的@param
標簽中指定前提條件。除此之外,文檔注釋中還應該描述方法的副作用,所謂副作用是指方法執(zhí)行后對系統(tǒng)狀態(tài)的影響。例如,如果方法啟動了后臺線程,文檔中就應該說明這一點。最后,文檔注釋也應該描述類或者方法的線程安全性。
案例說明
下面這個簡短的文檔注釋演示了一些常見用法。
/**
* Returns the element at the specified position in this list.
*
* <p>This method is <i>not</i> guaranteed to run in constant
* time. In some implementations it may run in time proportional
* to the element position.
*
* @param index index of element to return; must be
* non-negative and less than the size of this list
* @return the element at the specified position in this list
* @throws IndexOutOfBoundsException if the index is out of range
* ({@code index < 0 || index >= this.size()})
*/
E get(int index);
- 文檔注釋必須以
/**
開頭,否則Javadoc無法識別。 - 文檔注釋第一句話作為概要描述。概要描述必須獨立地描述目標元素的功能,同一個類或接口中的任意兩個成員或構造器,不應該具有相同的概要描述。即使是重載方法也不行。
- 每個參數(shù)都應該有一個
@param
標簽,標簽后面第一個單詞為參數(shù)名稱,接著是對該參數(shù)的解釋和要求。 - 返回類型非
void
的方法都應該有一個@return
標簽,描述返回值所表示的內(nèi)容。 - 該方法可能拋出的每一個異常,無論是受檢異常還是非受檢異常,都要對應一個
@throws
標簽。標簽后面第一個單詞為異常類型,接著是一句話,應該以if
開頭,描述該異常將在什么情況下被拋出。@param
、@return
和@throws
都不以句點結束。 -
@code
標簽可用于任何需要展示代碼的地方,被該標簽包圍的內(nèi)容會以特殊的字體顯示,并且不對其中內(nèi)容做任何HTML解析。 - 按慣例,單詞“this”用在實例方法的文檔注釋中時,應該始終是指方法調(diào)用所在的對象。
- 可以用
@literal
標簽展示包含HTML元字符的句子。它除了不改變顯示樣式外,其余效果和@code
一樣。
更多用法
我們需要額外注意一下泛型、枚舉和注解的文檔注釋。
- 泛型的文檔注釋應該說明所有類型參數(shù)。
/**
* An object that maps keys to values. A map cannot contain
* duplicate keys; each key can map to at most one value.
*
* (Remainder omitted)
*
* @param <K> the type of keys maintained by this map
* @param <V> the type of mapped values
*/
public interface Map<K, V> {
// Remainder omitted
}
- 當為枚舉編寫文檔時,要確保在文檔中說明常量。
/**
* An instrument section of a symphony orchestra.
*/
public enum OrchestraSection {
/** Woodwinds, such as flute, clarinet, and oboe. */
WOODWIND,
/** Brass instruments, such as french horn and trumpet. */
BRASS,
/** Percussion instruments, such as timpani and cymbals. */
PERCUSSION,
/** Stringed instruments, such as violin and cello. */
STRING;
}
- 為注解類型編寫文檔時,要確保在文檔中說明所有成員,以及類型本身。使用動詞短語說明當程序元素具有這種類型的注解時它表示什么意思。
/**
* Indicates that the annotated method is a test method that
* must throw the designated exception to succeed.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ExceptionTest {
/**
* The exception that the annotated test method must throw
* in order to pass. (The test is permitted to throw any
* subtype of the type described by this class object.)
*/
Class<? extends Exception> value();
}
另外,類是否是線程安全的,應該在文檔中說明它的線程安全級別。如果類是可序列化的,就應該在文檔中說明它的序列化形式。Javadoc具有繼承方法注釋的能力,如果API元素沒有文檔注釋,Javadoc會自動搜索最適用的接口或超類的文檔注釋,并且接口優(yōu)先于超類。
關注作者或文集《Effective Java》,第一時間獲取最新發(fā)布文章。