javadocコマンド入門

# 第６章：Javadocを生成する

今回は、Javadocの仕様や書き方といった実装面ではなく、
あくまでもjavadocコマンドの使い方、動作に絞って触れていきたいと思います。
コメントの書き方に関しては、Javadocの書き方に関する書籍などを学習した際に
まとめてみたいなと思います。

## Javadocの概要
Javadocコマンドは、Javaソースファイルにある宣言、コメントを解析し、デフォルトでは
public クラス、protected クラス、入れ子にされたクラス (匿名の内部クラスは除く)、
インタフェース、コンストラクタ、メソッド、およびフィールドについての実装ドキュメントを
HTML形式で生成します。

## Javadocのページ一覧
以降の説明をしやすくするため、javadocコマンドの成果物であるJavadocにはどういった
ページが生成されるのか、以下に例を示します。

### 基本内容ページ

- **概要ページ**(overview-summary.html)  
Javadocのトップページ。API、パッケージセットという全体の単位の概要が書かれている。
- **パッケージページ**(package-summary.html)  
パッケージごとに存在するページ。パッケージの概要が書かれている。
- **クラスページ/インタフェースページ**(classname.html)  
クラス、インターフェースごとに存在するページ。  
クラスに所属するメンバやメソッドに関する情報が書かれている。

〜概要ページ〜
<img width="1087" alt="スクリーンショット 2020-05-29 15.34.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/52623ebb-b75f-f724-441b-48aeb02c3e3c.png">

〜パッケージページ〜
<img width="1086" alt="スクリーンショット 2020-05-29 15.38.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/ee676349-d503-e02e-d082-71f390708235.png">

〜クラスページ〜
<img width="1084" alt="スクリーンショット 2020-05-29 15.38.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/3a3d6792-713a-8f46-469e-fc11b85b2b5a.png">

### 相互参照ページ

- **クラス階層ページ**(overview-tree.html)  
Javadoc1つに対して1つ存在する。所属する要素を階層化し、一覧できる。
- **クラス階層ページ**(package-tree.html)  
パッケージ1つに対して1つ存在する。パッケージに所属する要素を階層化し、一覧できる。
- **仕様ページ**(package-use.html)  
対象のクラス、インターフェースを使用しているパッケージやクラスなどを一覧できる。
- **非推奨APIページ**(deprecated-list.html)  
推奨されない(将来削除される可能性のある)クラス、メソッドなどを一覧できる。
- **定数フィールド値ページ**(constant-values.html)  
staticフィールドの値用のページ
- **直列化されたフォームページ**(serialized-form.html)  
直列化(外部化)可能なクラスに関するページ。
- **索引**(index-*.html)  
すべてのクラス、インタフェース、コンストラクタ、フィールド、およびメソッドが、  
アルファベット順に並んで一覧できる。

### サポートページ

- ヘルプページ(help-doc.html)  
ナビゲーションバーや各ページに関する説明が記載されている。

### HTMLフレーム
javadocコマンドは、2〜3つのHTMLフレームを作成する。
パッケージが1つの場合は左下にクラス用のフレーム、右側に詳細用のフレームが作成され、
パッケージが複数ある場合は左上にパッケージ用のフレームが追加される。

## javadocコマンドの形式

```shell
# javadocコマンドの引数の指定順序は任意です
$ javadoc [options] [packagenames | sourcefilenames] [-subpackages pkg1:pkg2:...]
```

- options  
javadocコマンドに渡されるコマンド行オプションです。
- packagenames  
処理対象のパッケージ名です。```java.lang java.awt```のように指定します。  
対象のパッケージを個別に指定する必要があり、ワイルドカードは使用できません。  
回帰的に指定するには、後述の```-subpackages```を使用します。
- sourcefilenames  
処理対象のソースファイル名です。 各ファイルはパスで始まり、アスタリスク (\*) などの  
ワイルドカードを含めることができます。
- -subpackages pkg1:pkg2:...  
ソースファイルから指定されたパッケージおよびそのサブパッケージ内に再帰的に  
ドキュメントを生成します。パッケージ名、ソースファイル名を指定する必要はありません。

## ソースファイルの指定

### ソースファイルの種類
Javadocを生成する際に解析される対象ファイルには、以下の4つがある。

- **クラスファイル**  
末尾が.javaのファイル。Javaの規約上無効なクラス名であった場合、処理対象外となる。  
例）数字で始まる。「-」を含む。など
- **パッケージコメントファイル**  
パッケージ毎に配置することが可能で、.javaのファイルと同じ階層に配置される。  
パッケージの概要について記載する。ファイル名が決まっており、以下2つの仕様がある。
    - JDK1.5より前：package.html
    - JDK1.5以降：package-info.java
- **概要コメントファイル**  
概要ページを生成するためのファイル。ファイル名、配置場所は任意だが、通常は  
overview.htmlにして、ソースツリーの最上位レベルに置く。  
-overview オプションを使って概要コメントファイル名を指定することで生成される。
- **doc-filesディレクトリ内のファイル**  
例えばSampleクラスというクラスのJavadocにおいて、画像ファイルを挿入したいなど  
.javaのルールから外れたファイルを使用したい場合、.javaと同じ階層にdoc-filesという  
ディレクトリを作成し配置することで、格納されたファイルを解析対象にできる。

### 様々なソースファイルの指定方法
ソースファイルの指定には、主に以下の3つの方法がある。

**１. パッケージを指定する**
ワイルドカードが使用できないため、以下の形式で半角スペースで区切りながら、
すべてのパッケージを個別で指定します。指定は完全指定である必要があります。
```java.lang java.lang.reflect java.awt```

**２. ソースファイルのパスを指定する**
ソースファイルのパスを指定します。絶対パス、相対パスどちらでも指定可能で、
相対パスの場合はカレントディレクトリからの相対パスを指定します。
ワイルドカードの使用が可能で、複数指定する場合は半角スペースで区切ります。
```/src/java/awt/Sample.java src/java/awt/*Bar.java```

**３. -subpackagesオプションで再帰的にパッケージを指定する**
パッケージを指定すると、サブパッケージを含めて指定範囲にすることができます。
ワイルドカードの使用はできません。指定時は、以下の形式でコロン(:)で区切り指定します。
```-subpackages　java:javax.swing```

> 通常はパッケージを個別で指定することは滅多にありません。
ソースファイルのパスをワイルドカードで指定するか、-subpackagesオプションで
再帰的に指定するのが主です。

**Ex. パッケージで指定する場合について**
ソースファイルをパッケージで指定する際は、
パッケージルートを指定しなければパッケージ階層をたどることはできません。
よって、パッケージの起点となるディレクトリを指定する必要があります。
ディレクトリの指定には、以下の2つの方法があります。

- カレントディレクトリを起点のディレクトリに移動させてjavadocコマンドを実行する
- -sourcepathオプションで起点のディレクトリを指定する

## javadocのオプション
javadocコマンドに渡せるオプションには、
「javadocコマンドのオプション」と「ドックレットが提供するオプション」の2つがあります。
ドックレットについては詳しく書きませんが、
javadocのフォーマットを提供するテンプレートのようなものだと思ってください。
明示的にカスタムのドックレットを指定しない場合は、標準ドックレットが選択されます。

### 主要なオプション

- -overview <パス¥ファイル名>  
任意の場所に配置したoverview.htmlをパスで指定することで、overview.htmlを解析し、  
概要ページ (overview-summary.html) に配置する。  
パスには、-sourcepathで指定したディレクトリからの相対パスを指定する。
- -d <パス>  
指定したパスに生成したJavadocを出力する。
- -source <バージョン>  
ソースコードのバージョンを指定する。バージョンはコンパイルのものに合わせる。  
    - 1.5 : JDK1.5で導入されたコードを受け付ける。デフォルト値。
    - 1.4 : JDK1.4で導入された、アサーションを含むコードを受け付ける。
    - 1.3 : JDK1.3以降に導入されたアサーション、総称、他の言語機能をサポートしない。
- -classpath <パスリスト>  
参照クラス(.class)を検索するパスを指定する。  
参照クラスは、ドキュメント化されるクラスに加え、それらのクラスが参照するすべての  
クラスを含む。指定したパス以下のサブディレクトリが検索範囲になる。
クラスパスが設定されていない場合は、カレントディレクトリがクラスパスになる。
- -sourcepath <パスリスト>  
ソースファイルのクラスパスを指定する。(パッケージまたは-subpackagesを渡す場合)   
指定したパス以下のサブディレクトリが検索範囲になる。このオプションを使って、  
-sourcepathを省略した場合、**クラスパスと同値**が設定され、  
-classpath も省略した場合は**カレントディレクトリ**が設定される。
- -J<javaコマンドのオプション>  
javadocを実行する実行時システムjavaにオプションを渡す。(-J-Xmx32mなど)

### ドキュメント化対象の指定系のオプション

- -subpackages  <パッケージ1:パッケージ2...>  
指定パッケージとそのサブパッケージ以下を生成範囲にできる。(複数パッケージの指定可能)  
-subpackagesを使用する場合は-sourcepathが必須である。
- -bootclasspath <パスリスト>  
ブートクラスが存在するパスを指定する。

### ドキュメント化対象の制御系のオプション

- -public  
publicクラスおよびメンバだけを表示する。
- -protected  
protectedおよびpublicのクラスとメンバだけを表示する。デフォルトの設定。
- -package  
package、protected、およびpublicのクラスとメンバだけを表示する。
- -private  
すべてのクラスとメンバを表示する。
- -exclude <パッケージ1:パッケージ2...>  
指定したパッケージとそのサブパッケージを-subpackagesで指定したリストから除外する。  

### ドックレット系のオプション

- -doclet <クラス>  
標準ドックレット以外のドックレットを指定する。完全指定で起動クラスを指定する。  
起動クラスの指定の形式は```-doclet com.example.doclets.SampleDoclet```。  
起動クラスへのクラスパスは、-docletpath オプションによって定義されます。
- -docletpath <クラスパス1:クラスパス2...>  
-docletオプションで指定したドックレット開始クラスファイル、および依存するjarファイル  
へのパスを指定する。開始クラスファイルが jar ファイル内にある場合はjarファイルのパス  
のみ指定でよい。絶対パスまたは現在のディレクトリからの相対パスを指定できる。  
目的のドックレット開始クラスが検索パス内にある場合は、このオプションは不要。

```shell
# SampleDockletは/src/com/example/doclets直下にあるとする
-doclet com.example.doclets.SampleDoclet -docletpath /src:/lib/doclet.jar
```

### デバッグ系のオプション

- -verbose  
javadocの実行中に詳細なメッセージを表示する。  
指定しない場合、ソースファイルのロード時とドキュメントの生成時(ソースファイルごと)、  
およびソート時(１回の実行で１回のみ)にメッセージが表示される。  
指定した場合、各Javaソースファイルの解析に要した時間(ミリ秒単位)など、詳細な  
メッセージが表示される。
- -quiet  
エラーメッセージ、警告メッセージ以外のメッセージを抑制する。

### 国際化系のオプション
- -locale <ロケール>  
Javadocのロケールを設定する。ロケールが設定されるのはJavadoc側で生成される  
テキスト群であって、ソースファイル内のコメントではない。  
**-localeは全てのドックレット系のオプションより左に設定する必要がある。**
- -encoding <エンコード名>  
ソースファイルのエンコーディング(EUCJIS/SJISなど)を指定する。このオプションが  
指定されていない場合は、プラットフォームのデフォルトコンバータが使われる。

## 実行
ここでは、今まで使ってきたサンプルコードにコメントとJavadoc生成用のファイル群を
追加した以下の構成をサンプルコードとします。
<img width="355" alt="スクリーンショット 2020-05-30 16.14.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/081ca477-a7da-99b5-b361-2d2e5eeedf80.png">

```java:UseCommons.java
package com.example.app;

import org.apache.commons.lang3.StringUtils;
import com.example.util.StrFactory;

/**
 * Apache Commonsを使用するためのクラスです。
 */
public class UseCommons {

	public static void main(String[] args) {
		System.out.println(CommonsHelper.returnNgStrIfHasProbrem(null));
		System.out.println(CommonsHelper.returnNgStrIfHasProbrem(""));
		StrFactory strFactory = new StrFactory();
		System.out.println(CommonsHelper.returnNgStrIfHasProbrem(strFactory.sayHelloWorld()));
	}

	static class CommonsHelper {
		static String returnNgStrIfHasProbrem (String target) {
			if (StringUtils.isEmpty(target)) {
				return "NG";
			} else if (StringUtils.isBlank(target)) {
				return "NG";
			}
			return target;
		}
	}
}
```
```java:StrFactory.java
package com.example.util;

/**
 * 様々な文字列を生成するためのファクトリークラスです。
 */
public class StrFactory {
	/**
	 * "Hello World!"という文字列を返却します。
	 */
	public String sayHelloWorld() {
		return "Hello World!";
	}
}
```
```html:package.html
<html>
<body>
サンプルのパッケージコメントです。
</body>
</html>
```
```html:overview.html
<html>
<body>
サンプルの概要コメントです。
</body>
</html>
```

上記の通り、ソースファイルを準備したら、以下のコマンドを実行します。

```shell
# カレントディレクトリは/java-sampleです。
$ javadoc -classpath ./src:./lib/commons-lang3-3.10.jar -subpackages com.example -overview ./overview.html -d ./docs
```

実行すると、出力先として指定した/java-sample/docsにJavadocが生成されます。
Javadocを見るには、index.htmlを開きます。
<img width="367" alt="スクリーンショット 2020-05-30 16.26.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/c55294c3-7328-a7e5-c644-148c249b5bd1.png">

以下、実際の出力です。
<img width="933" alt="スクリーンショット 2020-05-30 16.28.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/9a8c6e2e-ccd6-3c09-4116-d5821d5df25c.png">
<img width="933" alt="スクリーンショット 2020-05-30 16.28.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/1175ddfa-3487-e8e3-d5ab-879f553fd8d9.png">
![screencapture-file-Users-matsushitafuu-Documents-java-command-javac-docs-index-html-2020-05-30-16_28_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/78913c0d-33c1-5198-7c40-79c80e4f48a8.png)
![screencapture-file-Users-matsushitafuu-Documents-java-command-javac-docs-index-html-2020-05-30-16_29_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619923/913aabfc-0f61-5719-2134-c0cf283dcc72.png)

## おわりに
サンプルコードでは必要最低限のコメントもかけていませんが、
実際にはコメントにHTMLを使用したり、画像を挿入したり、外部のライブラリを参照したり
様々なことができますので、それらの実装に関しては専門書籍を読む、調べるなどして
勉強していただければと思います。

[メインページに戻る](https://qiita.com/maple_syrup/items/c0aa2eacb8f486dc52a8)