Java 23 から Markdown で JavaDoc コメントが書けるようになります(JEP 467: Markdown Documentation Comments)

blog1.mammb.com

openjdk.org


Markdown Documentation Comments

JDK23 より、JavaDoc コメントを Markdown 形式で記載できるようになります。

Markdown 形式のコメントは、Rust と同じように /// で始めます。

/// Returns a hash code value for the object. This method is
/// supported for the benefit of hash tables such as those provided by
/// [java.util.HashMap].
///
/// The general contract of `hashCode` is:
///
///   - Whenever it is invoked on the same object more than once during
///     an execution of a Java application, the `hashCode` method
///     must consistently return the same integer, provided no information
///     used in `equals` comparisons on the object is modified.
///     This integer need not remain consistent from one execution of an
///     application to another execution of the same application.
///   - If two objects are equal according to the
///     [equals][#equals(Object)] method, then calling the
///     `hashCode` method on each of the two objects must produce the
///     same integer result.
///   - It is _not_ required that if two objects are unequal
///     according to the [equals][#equals(Object)] method, then
///     calling the `hashCode` method on each of the two objects
///     must produce distinct integer results.  However, the programmer
///     should be aware that producing distinct integer results for
///     unequal objects may improve the performance of hash tables.
///
/// @implSpec
/// As far as is reasonably practical, the `hashCode` method defined
/// by class `Object` returns distinct integers for distinct objects.
///
/// @return  a hash code value for this object.
/// @see     java.lang.Object#equals(java.lang.Object)
/// @see     java.lang.System#identityHashCode
public native int hashCode();

マークダウンドキュメントは、CommonMark 仕様に基づきます(パーサはcommonmark-javaがコピーして取り込まれています)。

コメント行は /// で始め、それ以降に現れる文字に制限はありません。 ですので、以下のようなコメントを含むコードサンプルも書くことができます。

/// Here is an example:
///
/// ```
/// /** Hello World! */
/// public class HelloWorld {
///     public static void main(String... args) {
///         System.out.println("Hello World!"); // the traditional example
///     }
/// }
/// ```

空白行をコメントに含めるには、以下のようになります。

/// This is an example ...
///
/// ... of a 3-line comment containing a blank line.

以下のようなケースでは、別々のコメントとして扱われます。 この時、最後のコメントのみが、その後に続く宣言のためのJavaDocコメントとみなされます。

/// This comment will be treated as a "dangling comment" and will be ignored.

/// This is the comment for the following declaration.
public void m() { }

コメント内には、GitHub Flavored のテーブルも使えます。


リンク

JavaDocの {@link ...} タグは、要素への参照を角括弧で囲むだけです。

例えば、java.util.Listにリンクするには、[java.util.List]と記述します。 コード内にjava.util.Listimport文がある場合は、[List]と記述します。

/// - a module [java.base/]
/// - a package [java.util]
/// - a class [String]
/// - a field [String#CASE_INSENSITIVE_ORDER]
/// - a method [String#chars()]

代替テキストでリンクを作成するには、[text][element]という形式を使用します。例えば、a listというテキストでjava.util.Listへのリンクを作成するには、[a list][List]と記述します。 このリンクは標準的なJavaDocの {@linkplain ...} タグを使うのと同じです。

/// - [the `java.base` module][java.base/]
/// - [the `java.util` package][java.util]
/// - [a class][String]
/// - [a field][String#CASE_INSENSITIVE_ORDER]
/// - [a method][String#chars()]

角括弧はエスケープが必要です。例えば、String.copyValueOf(char[])へのリンクは [String#copyValueOf(char\[\])] のように記載します。


テーブル

GitHub Flavored Markdown で書くことができます。

/// | Latin | Greek |
/// |-------|-------|
/// | a     | alpha |
/// | b     | beta  |
/// | c     | gamma |

キャプションなどの機能はサポートされていません。


JavaDoc tags

{@inheritDoc} のようなインラインタグと、@param@return のようなブロックタグを使用できます。

/// {@inheritDoc}
/// In addition, this methods calls [#wait()].
///
/// @param i the index
public void m(int i) ...

前述のJavaDocタグは、コードスパン(`...`)やインデントされたテキストブロック、フェンス(``` や ~~~) の中では通常の文字として扱われます。

/// The following code span contains literal text, and not a JavaDoc tag:
/// `{@inheritDoc}`
///
/// In the following indented code block, `@Override` is an annotation,
/// and not a JavaDoc tag:
///
///     @Override
///     public void m() ...
///
/// Likewise, in the following fenced code block, `@Override` is an annotation,
/// and not a JavaDoc tag:
///
/// ```
/// @Override
/// public void m() ...
/// ```

{@inheritDoc} で異なる書式を使えます。

interface Base {
    /** A method. */
    void m()
}

class Derived implements Base {
    /// {@inheritDoc}
    public void m() { }
}

ユーザー定義の JavaDoc タグもMarkdownドキュメントで使用できます。

/// For more information on comments, see {@jls 3.7 Comments}.
///
/// @implSpec
/// This implementation does nothing.
public void doSomething() { }

JDKドキュメントでは、Java言語仕様へのリンクの短縮形として {@jls ...}、特定の情報のセクションを紹介するために @implSpec@implNote などのブロックタグを定義して使用しています。


シンタックスハイライト

フェンス付きコードブロックの冒頭のフェンスには、info string が続くことがあります。info string の最初の単語は、CSSクラス名を導き出すために使用され、JavaScriptライブラリによって構文の強調表示(Prismなど)やレンダリング図(Mermaidなど)を有効にするために使用できます。

CSSコードをシンタックスハイライトで表示することができます

/// ```css
/// p { color: red }
/// ```

javadoc --add-script オプションを使って、JavaScriptライブラリをドキュメントに追加することができます。