いまさら聞けない「Javadoc」と「アノテーション」入門:【改訂版】Eclipseではじめるプログラミング(22)(4/4 ページ)
これからプログラミングを学習したい方、Javaは難しそうでとっつきづらいという方のためのJavaプログラミング超入門連載です。最新のEclipseとJava 6を使い大幅に情報量を増やした、連載「Eclipseではじめるプログラミング」の改訂版となります
アノテーションを指定するには
アノテーションを指定したい場合は、次のように記述します。パッケージ、クラス、インターフェイス、フィールド、メソッド、パラメータ、コンストラクタ、ローカル変数の任意の宣言中で修飾子として指定できます。
@アノテーション型名 ( アノテーション要素名 = 値 )
複数のアノテーション要素を指定する場合は、次のようにカンマで区切って指定します。
@アノテーション型名 ( アノテーション要素名 = 値, アノテーション要素名 = 値 )
初期値が指定されていないアノテーション要素については、初期化子(「アノテーション要素名 = 値」)の指定が必要です。アノテーション要素の指定順は自由です。
初期値がすべて指定されている場合や、そもそもアノテーション要素を持たないアノテーション型を使う場合には、初期化子は空で指定できます。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用ライブラリではアノテーションの使用を前提としたものも多いので、使えるようにしておきましょう。
今回作ったサンプルのソースコードはこちらからダウンロードできます。
筆者紹介
小山博史(こやま ひろし)
情報家電、コンピュータと教育の研究に従事する傍ら、オープンソースソフトウェア、Java技術の普及のための活動を行っている。長野県の地域コミュニティである、SSS(G)やbugs(J)の活動へも参加している。
著書に「基礎Java」(インプレス)、共著に「Javaコレクションフレームワーク」(ソフトバンククリエイティブ)、そのほかに雑誌執筆多数。
- Javaの例外処理で知らないと損する7つのテクニック
- プログラマの宿命! 例外とエラー処理を理解する
- いまさら聞けない「Javadoc」と「アノテーション」入門
- 7ステップで理解するJavaでの列挙型/enum使用法
- 拡張for文の真の実力を知り、反復処理を使いこなせ
- キュー構造をJavaで実装してジェネリック型を理解する
- 強く型付けされているJavaの理解に必修の“型変換”
- あなたの知らない、4つのマニアックなJava文法
- “ネスト”した型で始める軽量Javaプログラミング!?
- Javaは「抽象クラス」で実装を上手に再利用できる
- 再利用性の高いクラス作成に重要な“アクセス制御”
- “コンストラクタ”と初期化、本当に理解できてる?
- 継承やオーバーライドで簡単にクラスを“拡張”しよう
- 「static」でクラス共有の変数・メソッドを使いこなせ!
- Javaの実案件に必須のパッケージとインポートを知る
- プログラムを「変更」しやすくする“インターフェイス”
- Javaの参照型を文字列操作で理解して文法を総復習
- クラスの振る舞いを表すJavaの“メソッド”とは?
- 複雑なデータを表現できるクラスやフィールドって?
- データ集合を扱うのに便利なJavaの配列と拡張for文
- プログラミングの真骨頂! Javaで“反復処理”を覚える
- プログラミングの醍醐味! Javaで“条件式”を理解する
- Javaで一から理解するプログラムの変数と演算子
- Eclipse 3.4で超簡単Javaプログラミング基礎入門
Copyright © ITmedia, Inc. All Rights Reserved.