【コラム】

ライトニングJava

28 アノテーション(3) - アノテーションを知る(2)

    後藤大地  [2005/11/28]

    Java SE 5.0 TigerのコアAPIでは、@Deprecatedが採用されている程度しかアノテーションは使われていないことを説明した。コアAPIにおけるアノテーションの本格的な採用はJava EE 5.0やJava SE 6.0 Mustang以降になるのだろう。

    まず、もっとも簡単なカスタムアノテーションの実装を通じて、アノテーションがどのように実現されているのかを調べてみよう。

    簡単なカスタムアノテーション

    もっとも簡単なアノテーションタイプの例をリスト1に示す。リスト1はNothingというカスタムアノテーションを定義するもので、この場合はマーカアノテーションを定義していることになる。

    リスト1 アノテーションタイプの例 - Nothing.java

    @interface Nothing { }

    つぎに、作成したアノテーションを使用したソースコードの例をリスト2に示す。ここではクラス、メソッド、ローカル変数に対してアノテーションを指定している。リスト1およびリスト2をコンパイルして実行すると、Welcome to the annotation worldという文字列が標準出力に出力される。

    リスト2 カスタムアノテーションの使用例 - Test.java

    @Nothing
    public class Test
    {
        @Nothing
        public static void main(String[] anyArguments)
        {
            @Nothing String message = "Welcome to the annotation world";

            System.out.println(message);
        }
    }

    ここで注目するべきは、アノテーションを挿入しているものの、プログラム本来の動きにはまったく影響を与えていないことにある。アノテーションだけでは、プログラムの動作に対してなんら影響を与えない。挿入されているアノテーションを使用するときにはじめてアノテーションが本当の効果を発揮することになる。

    アノテーションの仕組みを探る

    アノテーションタイプやアノテーションを含んだ.classファイルを逆コンパイルして、実際にアノテーションがどのように実現されているかを調べてみよう。リスト1およびリスト2を逆コンパイルしたものをリスト3およびリスト4に示す。

    アノテーションタイプを逆コンパイルした結果リスト3に注目してほしい。ここではjava.lang.annotation.Annotationを継承したインターフェースとして認識されていることがわかる。これがアノテーション定義の実体だ。

    リスト3 Nothing.javaをコンパイルしたものを逆コンパイルした結果

    import java.lang.annotation.Annotation;

    interface Nothing extends Annotation
    {
    }

    次に、アノテーションを挿入したクラスを逆コンパイルした結果だが、こちらにはアノテーションがどこにも表示されていないことがわかる。これは逆コンパイルを実行するアプリケーションがアノテーションを認識していないことが原因なのだが、ようするに、従来の仕組みではアノテーション部分はコードとしては認識されていないということがわかるだろう。

    リスト4 Test.javaをコンパイルしたものを逆コンパイルした結果

    import java.io.PrintStream;

    public class Test
    {
        public static void main(String args[])
        {
            String s = "Welcome to the annotation world";
            System.out.println(s);
        }
    }

    アノテーションはどこに?

    ではアノテーション情報はどこにいったのかということになる。strings(1)を使ってクラスファイルの内容をなでてみると、RuntimeInvisibleAnnotations LNothing;という記述が見える。.classファイルにアノテーションの情報は含まれていることはわかる。

    リスト5 Test.classをstrings(1)で処理した結果

    <init>
    Code
    LineNumberTable
    main
    ([Ljava/lang/String;)V
    RuntimeInvisibleAnnotations
            LNothing;
    SourceFile
            Test.java
    Welcome to the annotation world
    Test
    java/lang/Object
    java/lang/System
    Ljava/io/PrintStream;
    java/io/PrintStream
    println
    (Ljava/lang/String;)V

    javap(1)コマンドを使って.classファイルを表示すると、たしかにRuntimeInvisibleAnnotationsやLNothing;の記述があることがわかる。Java SE 5.0 Tigerから.classファイルのフォーマットも変更され、アノテーション情報が挿入されている。

    リスト6 Test.classをjavap(1)で処理した結果

    Compiled from "Test.java"
    public class Test extends java.lang.Object
      SourceFile: "Test.java"
      RuntimeInvisibleAnnotations: length = 0x6
       00 01 00 0E 00 00
      minor version: 0
      major version: 49
      Constant pool:
    const #1 = Method       #6.#17; //  java/lang/Object."<init>":()V
    const #2 = String       #18;    //  Welcome to the annotation world
    const #3 = Field        #19.#20;        //  java/lang/System.out:Ljava/io/PrintStream;
    const #4 = Method       #21.#22;        //  java/io/PrintStream.println:(Ljava/lang/String;)V
    const #5 = class        #23;    //  Test
    const #6 = class        #24;    //  java/lang/Object
    const #7 = Asciz        <init>;
    const #8 = Asciz        ()V;
    const #9 = Asciz        Code;
    const #10 = Asciz       LineNumberTable;
    const #11 = Asciz       main;
    const #12 = Asciz       ([Ljava/lang/String;)V;
    const #13 = Asciz       RuntimeInvisibleAnnotations;
    const #14 = Asciz       LNothing;;
    const #15 = Asciz       SourceFile;
    const #16 = Asciz       Test.java;
    const #17 = NameAndType #7:#8;//  "<init>":()V
    const #18 = Asciz       Welcome to the annotation world;
    const #19 = class       #25;    //  java/lang/System
    const #20 = NameAndType #26:#27;//  out:Ljava/io/PrintStream;
    const #21 = class       #28;    //  java/io/PrintStream
    const #22 = NameAndType #29:#30;//  println:(Ljava/lang/String;)V
    const #23 = Asciz       Test;
    const #24 = Asciz       java/lang/Object;
    const #25 = Asciz       java/lang/System;
    const #26 = Asciz       out;
    const #27 = Asciz       Ljava/io/PrintStream;;
    const #28 = Asciz       java/io/PrintStream;
    const #29 = Asciz       println;
    const #30 = Asciz       (Ljava/lang/String;)V; {
    public Test();
      Code:
       Stack=1, Locals=1, Args_size=1
       0:   aload_0
       1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
       4:   return
      LineNumberTable:
       line 2: 0

    public static void main(java.lang.String[]);
      Code:
       Stack=2, Locals=2, Args_size=1
       0:   ldc     #2; //String Welcome to the annotation world
       2:   astore_1
       3:   getstatic       #3; //Field java/lang/System.out:Ljava/io/PrintStream;
       6:   aload_1
       7:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       10:  return
      LineNumberTable:
       line 7: 0
       line 9: 3
       line 10: 10
      RuntimeInvisibleAnnotations: length = 0x6
       00 01 00 0E 00 00

    }

    このアノテーション情報を使って、クラスのロード時や実行時に処理を行おうとするのが、アノテーションのもたらす本質的な効果ということになる。

    アノテーションを処理 apt(1)

    アノテーションを処理するには、特定のメソッドを実装したアノテーションを処理するクラスを作成する。アノテーションは作成したクラスの処理を通じて処理されるようになる。Java SE 5.0 Tigerからはアノテーションを処理する外部コマンドとしてapt(1) (Annotation Processing Tool)も付属している。

    アノテーションは用意された機能を使う分には簡単だが、カスタムアノテーションを定義し、定義したアノテーションを処理する実装を行うのは、なかなか面倒くさい。この点はGeneric Javaと同じだ。Generic Javaやアノテーションは、使い分には便利なEoDだが、作る方はなかなか骨がおれる。

    リスト1およびリスト2は簡単な例だが、アノテーション実装の基本となるものだ。このくらいの実装はそのまま覚えてしまおう。

    提供:毎日就職ナビ

    会員登録はこちら

    学生のための就職情報サイト「毎日就職ナビ」。4,000社以上の新卒採用情報が常時掲載され、社内の雰囲気が伝わる情報画面、さまざまな項目での会社検索、エントリーや説明会検索など、機能も充実。無料適職診断、就活Q & A、エントリーシート添削講座など、就職活動に役立つ記事も満載です。研究者、エンジニアを目指す学生の方々も是非エントリーしてください。お待ちしています!

    毎日コミュニケーションズ 就職情報事業本部はプライバシーマークを取得しています。

    新着記事

    特設サイトの情報

      求人情報

      人気記事

      一覧

      イチオシ記事

      新着記事

      特別企画

      転職ノウハウ

      あなたの仕事適性診断

      4つの診断で、自分の適性を見つめなおそう!

      Heroes File ~挑戦者たち~

      働くこと・挑戦し続けることへの思いを綴ったインタビュー

      はじめての転職診断

      あなたにピッタリのアドバイスを読むことができます。

      転職Q&A

      転職に必要な情報が収集できます

      スカウト転職する

      企業からアプローチのメッセージが届きます。

      マイナビニュースマガジン