
いまさら聞けない「Javadoc」と「アノテーション」入門
株式会社ガリレオ
小山博史
2011/5/19
アノテーションを指定するには
アノテーションを指定したい場合は、次のように記述します。パッケージ、クラス、インターフェイス、フィールド、メソッド、パラメータ、コンストラクタ、ローカル変数の任意の宣言中で修飾子として指定できます。
@アノテーション型名 (
アノテーション要素名 = 値
)
複数のアノテーション要素を指定する場合は、次のようにカンマで区切って指定します。
@アノテーション型名 (
アノテーション要素名 = 値,
アノテーション要素名 = 値
)
初期値が指定されていないアノテーション要素については、初期化子(「アノテーション要素名 = 値」)の指定が必要です。アノテーション要素の指定順は自由です。
初期値がすべて指定されている場合や、そもそもアノテーション要素を持たないアノテーション型を使う場合には、初期化子は空で指定できます。sample22.app10.Aクラスのm1メソッドを見てください。
初期化子を空で指定できる場合は、そもそも初期化子の指定を省略できます。sample22.app10.Aクラスのm2メソッドを見てください。
package sample22.app10;
public class A {
@Deprecated() void m1() {}
@Deprecated void m2() {}
}
■ アノテーション型の3つの分類
アノテーション型は、フルアノテーション型、単一値アノテーション型、マーカーアノテーション型、に分類できます。
- フルアノテーション型
単一値アノテーション型、マーカーアノテーション型以外のアノテーション型。複数の値を持つことができる - 単一値アノテーション型
valueという名前の要素だけを持つアノテーション型。アノテーションを記述するときには、値を1つ指定できる - マーカーアノテーション型
クラスやメソッドなどに印を付けるために使うアノテーション型
■ 単一値アノテーション型で要素名が「value」の場合
単一値アノテーション型の例としては、先ほど紹介したSuppressWarningsがあります。このアノテーション型では、String[]型の要素valueが定義されています。String配列型なので、使用時には次のようにString配列を1つ指定できます。
@SuppressWarnings(value = {"serial","unchecked","deprecation"})
class A {}
配列の要素が1つしかないときは、初期化子には「value = {"unchecked"}」と指定すればいいのですが、配列の要素を囲む{}を省略できるようになっています。つまり、次のように書くことができます。
@SuppressWarnings(value = "unchecked")
class B {}
実は、SuppressWarningsの要素は1つで名前がvalueなので、この場合は、要素名を省略できます。要素を1つしか持たないアノテーション型で、要素名がvalueでない場合は、このような要素名は省略できません。
@SuppressWarnings({"serial","unchecked","deprecation"})
class C {}
sample22.app11.Appクラスにこれらの例を入れておきました。サンプルなのでクラスへ一括で付けていますが、通常はもっと狭い範囲で付けます。また、実際には抑制すべきコンパイルエラーがないので、sample22.app11.Appクラス内の内部クラスに付けたアノテーションでは、コンパイラの警告が付きます。
アノテーションの注釈「メタアノテーション」とは
アノテーションは、その用途に応じて、どのプログラム要素へ付けるかが決まります。例えば、ClassInformationはクラスに付けるものであり、メソッドへ付けても仕方がありません。このため、アノテーションを間違ったプログラム要素へ付けないように気を付ける必要があります。
Javaでは、アノテーション型にTargetアノテーションを付けることで、こういった間違ったアノテーション型の利用をチェックできます。ちなみに、java.lang.annotation.Targetアノテーション型のように、アノーテション型に付けるアノーテションのことを「メタアノテーション(meta-annotation)」と言います。
メソッド情報用のアノテーションとしてMethodInformationアノテーション型を用意したとします。Targetアノテーション型は標準で用意されているアノテーションで、java.lang.annotation.ElementType型配列だけを要素に持ち、その要素名はvalueです。
ElementType型はプログラム要素の種類を表すenum型で、「ANNOTATION_TYPE」「CONSTRUCTOR」「FIELD」「LOCAL_VARIABLE」「METHOD」「PACKAGE」「PARAMETER」「TYPE」といった定数が定義されています。名前から意味は分かるはずです。TYPEはクラス、インターフェイス(アノテーションを含みます)、enum型の宣言と対応します。
これらを使って、次のように指定します。ElementType.METHODを指定することにより、MethodInformationアノテーションはメソッドにだけ付けられます。
package sample22.app12;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
public @interface MethodInformation {
}
ClassInformationアノテーションはクラスに付けるので、ElementType.TYPEを指定すればいいということです。
package sample22.app12;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
public @interface ClassInformation {
String author();
double version() default 1.0;
String dependon();
}
アノテーションを使い分ける「リテンションポリシー」とは
これまでアノテーションを参照するのは開発者だけではなく、EclipseやJavaコンパイラなどの開発用プログラムも参照するということを説明しました。
このことから分かるように、プログラムがアノテーションを参照できると便利な場面が多いため、アノテーションをプログラム実行時にも利用できるようにしたいことがあります。一方で、プログラム実行時には不要なアノテーションもあり、プログラムサイズを小さくしたい場合には、情報が残っていると邪魔になることもあります。
そのため、指定したアノテーションについて、「どのタイミングでアクセスができるようにしておくか」を、アノテーション型を定義するときに指定できるようになっています。
具体的には、java.lang.annotation.Retentionアノテーション型を使います。指定できる値はjava.lang.annotation.RetentionPolicy型で定義されています。これはenum型で、次の3つの定数があります。
- SOURCE
クラスを生成するときにコンパイラにより破棄 - CLASS
クラスファイルには存在。ただし、実行時には破棄 - RUNTIME
実行時に利用可能
java.lang.annotation.Retentionアノテーションを指定しない場合は、java.lang.annotation.RetentionPolicy.CLASSが適用されます。ただし、ローカル変数に対するアノテーションは、コンパイラに破棄されます。
最近のJava開発では、アノテーションは必須!
Javaではアノテーション型を使うことで、ソースコードへアノテーションを埋め込めます。アノテーションを使うことにより、コンパイラやプログラム実行環境へプログラムについての付加情報を伝えて特別な動作ができることを理解できたでしょうか。
java.langパッケージに含まれるアノテーション型、Deprecated、Override、SuppressWarningsは使えるようにしておきましょう。java.lang.annotationパッケージのTarget、Retentionについては、最初はそういうものがあると知っていれば十分です。
この他にも、今回は説明していませんが、java.lang.annotationパッケージに含まれる、「Documented」「Inherited」といったものもあり、JDK 6からはたくさんのアノテーションが追加されています。興味のある方は、「java.lang.annotation (Java Platform SE 6)のAPIリファレンス」などで調べてみてください。
本記事では、Javadocコメントとメタデータについて説明したうえで、Java標準アノテーション型の中でも重要なDeprecated、Override、SuppressWarningsについて、基本的な使い方を説明しました。また、独自のアノテーション型を定義したり利用したりする方法について説明しました。最近の実用的なJava用ライブラリではアノテーションの使用を前提としたものも多いので、使えるようにしておきましょう。
今回作ったサンプルのソースコードはこちらからダウンロードできます。
■ @IT関連記事
| J2SE
5.0「Tiger」で何が変わるか? J2EE Watch (6) Javaの登場以来もっとも大胆な言語仕様の変更が行われたJ2SE5.0。その仕様の変更点とメリットについて整理してみよう 「Java
Solution」フォーラム 2004/10/16 |
| Java SE コアAPI 使用コード例一覧 Java開発者/プログラマのための、Java SEコアAPIの使用コード例の記事へのJavadocっぽいリンク集。メソッドやコンストラクタ、例外などAPIの使い方の参考にしてください 「Java Solution」フォーラム 2009/3/24 |
| 筆者プロフィール |
| 小山博史(こやま ひろし) 情報家電、コンピュータと教育の研究に従事する傍ら、オープンソースソフトウェア、Java技術の普及のための活動を行っている。長野県の地域コミュニティである、SSS(G)やbugs(J)の活動へも参加している。 著書に「基礎Java」(インプレス)、共著に「Javaコレクションフレームワーク」(ソフトバンククリエイティブ)、そのほかに雑誌執筆多数。 |
| Index | ||||||||||
|
||||||||||
【改訂版】Eclipseではじめるプログラミング バックナンバー 連載インデックスへ»
- 第1回 Eclipse 3.4で超簡単Javaプログラミング基礎入門
- 第2回 Javaで一から理解するプログラムの変数と演算子
- 第3回 プログラミングの醍醐味! Javaで“条件式”を理解する
- 第4回 プログラミングの真骨頂! Javaで“反復処理”を覚える
- 第5回 データ集合を扱うのに便利なJavaの配列と拡張for文
- 第6回 複雑なデータを表現できるクラスやフィールドって?
- 第7回 クラスの振る舞いを表すJavaの“メソッド”とは?
- 第8回 Javaの参照型を文字列操作で理解して文法を総復習
- 第9回 プログラムを「変更」しやすくする“インターフェイス”
- 第10回 Javaの実案件に必須のパッケージとインポートを知る
- 第11回 「static」でクラス共有の変数・メソッドを使いこなせ!
- 第12回 継承やオーバーライドで簡単にクラスを“拡張”しよう
- 第13回 “コンストラクタ”と初期化、本当に理解できてる?
- 第14回 再利用性の高いクラス作成に重要な“アクセス制御”
- 第15回 Javaは「抽象クラス」で実装を上手に再利用できる
- 第16回 “ネスト”した型で始める軽量Javaプログラミング!?
- 第17回 あなたの知らない、4つのマニアックなJava文法
- 第18回 強く型付けされているJavaの理解に必修の“型変換”
- 第19回 キュー構造をJavaで実装してジェネリック型を理解する
- 第20回 拡張for文の真の実力を知り、反復処理を使いこなせ
- 第21回 7ステップで理解するJavaでの列挙型/enum使用法
- 第22回 いまさら聞けない「Javadoc」と「アノテーション」入門
- 第23回 プログラマの宿命! 例外とエラー処理を理解する
- 第24回 Javaの例外処理で知らないと損する7つのテクニック
| Java Solution全記事一覧 |
TechTargetジャパン
- Scalaのパッケージ、アクセス修飾子、オブジェクト継承 (2012/5/22)
インポート、パッケージオブジェクト、抽象クラス/抽象メソッド、オーバーライド、final、シールドクラスなども - 基幹系システムでCloud SQLは使えるか試してみた (2012/5/17)
サンプルとしてMRPシステムを作成して動かし、「再帰呼び出し」などのパフォーマンスを測定して検証してみます - アジャイル管理ツール9選+Pivotal Tracker入門 (2012/5/14)
群雄割拠のアジャイルプロジェクト管理ツールを9つ紹介し、特に注目を集めているPivotal Trackerの基本的な使い方を解説します - サーバサイドJSやJavaでWebアプリが作れるXPages (2012/5/11)
Notes/Dominoの資産をサーバサイドJavaScriptやJavaで操作し、HTMLやJavaScript、CSSをUIにできる技術を紹介
|
|
キャリアアップ
スポンサーからのお知らせ
- - PR -
イベントカレンダー
- - PR -
