アノテーション

いかに早くコーディングするか!
と考えたときに使った技の一つがアノテーションでした。
使ってみると結構便利です。
だもんで、アノテーションのあれこれをメモ。


インターフェースを作る


まずはインターフェースを作ります。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.TYPE, ElementType.FIELD })
public @interface Sample {

String[] value();
}



RetentionPolicyについて
  • SOURCE(ソース・コード)

  • コンパイラは、アノテーションの情報を読み込んで利用するが、クラス・ファイルには出力せずに捨ててしまう。つまり、アノテーションの情報は、ソース・コード上のみに保持される
  • CLASS(クラス・ファイル)

  • コンパイラは、アノテーションの情報をクラス・ファイルに出力する。ただし、リフレクションAPI経由で、実行時にその情報にアクセス※7することはできない
  • RUNTIME(実行時)

  • コンパイラは、アノテーションの情報をクラス・ファイルに出力する。実行時に、リフレクションAPI経由でその情報にアクセスできる

RetentionPolicyについては上記の通りです。
多分RUNTIME以外はあんまり使うことはないのかな。

ElementTypeについて
  • ElementType.ANNOTATION_TYPE

  • アノテーション型に指定できることを示す。
  • ElementType.CONSTRUCTOR

  • コンストラクタに指定できることを示す。
  • ElementType.LOCAL_VARIABLE

  • ローカル変数に指定できることを示す。
  • ElementType.FIELD

  • フィールドに指定できることを示す。
  • ElementType.METHOD

  • メソッドに指定できることを示す。
  • ElementType.PACKAGE

  • パッケージに指定できることを示す。
  • ElementType.PARAMATER

  • メソッド引数に指定できることを示す。
  • ElementType.TYPE

  • クラス、またはインタフェース(アノテーション型を含む)、enum型に指定できることを示す。


アノテーションをコードに埋め込む



@Sample ( { "test", "annotation" })
private Integer test;



今回のサンプルは、上記のようにクラスフィールドに対してアノテーションを定義できます。

リフレクションを使ってアノテーションの値を取得する

リフレクションを使ってアノテーションで設定された値を取得してみましょう!


// クラスのフィールドを取得する
Field[] hogeFields = hogeClass.getDeclaredFields();
Sample sample = hogeFields[0].getAnnotation(Sample.class);
if (sample != null) {

String[] sampleValues = sample.value();
}




これだけでOKです。
sampleValues[0]:"test"
sampleValues[1]:"annotation"


が取得できます。
利用シーンはかなり限定されると思いますが、ちょいちょい使いどころはあると思います。

ちょっと思ったこと・・・

今回のサンプルのようなアノテーションの使用方法は、フレームワークのようなアプリケーションの基盤となるような部分で使用されるべき技術だと思います。私がアノテーションを使うことになった理由ははっきり言って「逃げ」です。
アプリケーションを連携させるような仕事をしたときに、あまりに時間がなく、あまりに統一性がなくほとほと困り果てました。自分の会社の人間だけでやってるのであればいいのですが、複数の会社が関わっていたのでいちいち調整するのが面倒でした。ってかそんな時間はありませんでした。そんなときに各アプリの差異を吸収する手段としてアノテーションを使いました。結果としてはうまくいったのですが、かなり後悔してます。
と言うのが、各アプリの差異ってのは具体的に言うと、各アプリが保持しているDBのカラム名称とデータ型です。同じデータを入れるべき入れ物の名称が違う、データ型が違う、というのが多発したのです。連携させることを前提に打ち合わせが行われていたはずなのにメチャクチャでした。仕様がかたまった後に私は参加したので、なんでそんなにいい加減な仕事をしたのか知りませんが、あるべき姿にしようとするとかなり時間必要だな・・・、コーディングでごまかそう!と決意しました(あるべき姿にするための時間は無いと判断したので)。
アノテーションとリフレクションを駆使してどうにかできましたが、作った人意外絶対に解読できません。解読できたとしてもなんでアノテーションを使ってるのか絶対に分りません。今から考えると最低なコーディングをしてしまったと後悔です。

0 コメント: