Java 2 SDK 1.5 から言語仕様として追加されるメタデータ。 新しい言語使用であり、似たものとしては C# の属性ぐらいか ? ということで、少し触れてみることにしました。 なお、記述内容には誤りを含む可能性があります。 このページ自体が暫定情報です。あらかじめご了承ください。
まず、コンパイルする際の注意から。1.5 で追加された機能を使用するうには、 コンパイル時を含め、Javadoc を使用する際にも -source オプションで 1.5 を指定する必要があります。コンパイル時はさらに -target オプションに 1.5 を指定する必要もあります。
このメタデータ、いったい何に使うのでしょうか ? 直接プログラムの実行にかかわるものではありません (関わらせることはできるでしょう)。メタデータという名前のとおり、 これはメソッドやクラスなどそのものについての追加情報を示します。 従って、コンパイラやなんらかの変換を行うソフトウェアなど、 主にツールによって使用されることが多くなると思います。
コア API に追加されたメタデータ定義を見ていきます。
deprecated という単語、これはメソッドなどの非推奨を表します。 これまでにも Javadoc で @deprecated タグを使用することで、 コンパイル時に非推奨のメソッドなどを使用すると 警告を発生させることができました。
まずは、非推奨とするメソッドを作ります。
このソースをコンパイルしておきます。続いて、 非推奨メソッドを使用するテストプログラムを用意します。
なお、java.lang.Deprecated メタデータ定義には、 メタ情報はふくまれていないため、@Deprecated の後ろの ( ) (括弧) はなくても OK です。
Java では、メソッドのオーバーライド時に特別な識別子を必要としません。 次に、オーバーライドしようとしてメソッド名をタイプミスしてしまった 例を示します。
実行すると "function()." が出力されます。サンプルは単純なのですぐに 解決できるかもしれませんが、ソースがたくさんあると、 タイプミスを発見しなくてはなりません。このような場合に Overrides を使用していると、コンパイラがエラーを出してくれます。
このコードをコンパイルすると、functien() メソッドがスーパークラスのメソッドをオーバーライドしていないことを示す エラーが出力されます。1.5 Beta 時点で、 まだコンパイラの出力するメッセージが完全でないように思いますが、 今後改良されるでしょう。余計なバグを発生させないために有用だといえます。
Java でコーディングする場合、Javadoc API リファレンスは必須です。 メタデータについても API リファレンスにドキュメント化が行われています。 当然、リファレンスをみてそのメタデータが使えなくてはいけません。
先ほど見た Deprecated の Javadoc リファレンスを見てください。 リファレンスは The Source for Java Developers (http://java.sun.com/) で公開されています。以下のような記述があります。
ここから、Deprecated の使い方がわかるわけです。まず、@Documented ですが、 これは java.lang.annotation パッケージで定義されています。 これはコーディングには関係ありません。Javadoc が @Documented メタ情報のついたメタデータ定義が使用されているのを発見すると、 これを Javadoc ドキュメントに出力します (わかりにくい説明ですが、とりあえず Javadoc に使用するようです)。たとえば、先ほど取り上げた Deprecated のサンプルクラスを Javadoc でドキュメント化してください。 メソッドの説明のところに、@Deprecated と記されます。
次に @Retention ですが、ここで、value = SOURCE と記されています。 value は Retention (java.lang.annotation.Retention) のメンバとして定義されています。型は RetentionPolicy という Enum です。 RetentionPolicy を参照すると、いくつかの定数が定義されています。 その定数を "value =" に対して指定しています。ここでは SOURCE とされていますので、これはソースで有効ということになります。 すなわち、Retention はそのメタ情報がどの時点まで有効かをあらわしています。 SOURCE 以外には CLASS や RUNTIME があります。 CLASS はクラスファイルにメタ情報が含まれますが、Java VM はその情報を保持しません。RUNTIME は Java VM が保持するため、 実行時に利用されます。リフレクションによって使用する場合は RUNTIME を指定する必要があります。
public @interface Deprecated、これは Deprecated がメタデータとして定義され、 アクセス修飾子が public であることを示します。メタデータの定義は @interface が使われるわけですね。
他に重要なものには Target があります。java.lang.annotation.Target の API ドキュメントを参照してください。ElementType の配列型を示す value というメンバが定義されています。そこで、ElementType を参照すると、 このメタ情報の利用場所を示す定数が定義されています。すなわち、 @Target というメタ情報のついたメタデータ定義は、そこで指定されている箇所で 使用できることを表します。
メタデータの定義自体にメタ情報が付加されているのが、 ぱっと見にややこしいところです。
簡単にわかる範囲でメタデータについて書きましたが、 まだ完全には理解できてません。従っておかしなところもあるかと思います。 また、1.5 正式リリースまでに細部の変更があるかもしれません。 しばらく注目し、新たな発見があればこのページも更新するかもしれません。