倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

アノテーションを付加するターゲット

自作のアノテーションを作成するときにターゲットとなる要素を考える必要がありますが、そのときに必要となる java.lang.anntotation.ElementType の使用方法をメモ。

java.lang.annotation.ElementType 一覧

ElementType の要素 アノテーションを付加できる対象
ElementType.TYPE インターフェース、クラス、列挙型などの Java の型の定義に付加する。
ElementType.CONSTRUCTOR コンストラクタに付加する。
ElementType.FIELD フィールドに付加する。 列挙型の要素にも付加可能。
ElementType.METHOD クラス等のメソッドに付加する。 アノテーション定義のメソッド宣言にも付加可能
ElementType.PARAMETER パラメータに付加する。 メソッド宣言の引数の箇所。 インターフェースのメソッド宣言に書くパラメータにも付加可能。
ElementType.LOCAL_VARIABLE ローカル変数に付加する。
ElementType.ANNOTATION_TYPE アノテーション定義に付加する。
ElementType.PACKAGE パッケージに付加する。 付加方法は後述。

サンプルのためのアノテーション定義


後述のサンプルコードに付加するアノテーションを定義しておきます。 大まかに言って ElementType.XXXX に対して @OnXxxx アノテーションを定義しています(いくつか少し変えてますが):

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

@Target(ElementType.TYPE)
@interface OnType {}

@Target(ElementType.CONSTRUCTOR)
public @interface OnConstructor {}

@Target(ElementType.FIELD)
public @interface OnField {}

@Target(ElementType.METHOD)
public @interface OnMethod {}

@Target(ElementType.PARAMETER)
public @interface OnParam {}

@Target(ElementType.LOCAL_VARIABLE)
public @interface OnVariable {}

@Target(ElementType.ANNOTATION_TYPE)
public @interface OnAnnotation {}

@Target(ElementType.PACKAGE)
public @interface OnPackage {}

サンプルコード


以下で見ていくサンプルは

です。

★クラスを用いたサンプル★

まずは通常のクラスに対して上記のアノテーションを付加したサンプル。 private フィールドやそれに対するアクセッサメソッドを定義した通常のクラスです。 Person#setBirthYear() メソッドは、@OnVariable アノテーションを使いたいが為に定義したメソッド。 内容はあまり気にしないで下さい。

使用しているアノテーション

  • @OnType
  • @OnField
  • @OnConstructor
  • @OnMethod
  • @OnParam
  • @OnVariable

です。

package org.waman.sample.annotation;

@OnType
public class Person{

    @OnField private String name;
    @OnField private int age;
    
    @OnConstructor
    public Person(@OnParam String name, @OnParam int age){
        this.name = name;
        this.age = age;
    }

    @OnMethod
    public String getName() {
        return this.name;
    }

    @OnMethod
    public void setName(@OnParam String name) {
        this.name = name;
    }

    @OnMethod
    public int getAge() {
        return this.age;
    }

    @OnMethod
    public void setAge(@OnParam int age) {
        this.age = age;
    }
    
    @OnMethod
    public void setBirthYear(int year){
        @OnVariable int currentYear = Calendar.getInstance().get(Calendar.YEAR);
        setAge(currentYear - year);
    }
}

★インターフェースを用いたサンプル★

クラスを用いたサンプルと大して変わりませんが、インターフェースバージョンも載せておきます。

IPerson#WAMAN フィールドは、インターフェースのフィールドにも @OnField が付加できることを見せるためだけに定義してます*1

package org.waman.sample.annotation;

@OnType
public interface IPerson {
    
    @OnField Person WAMAN = new Person("waman", 100);
    
    @OnMethod
    void setName(@OnParam String name);

    @OnMethod
    void setAge(@OnParam int age);
}

インターフェースのメソッド宣言のパラメータにも @OnParam アノテーションを付加することができます。

★列挙型を用いたサンプル★

次は列挙型についてのサンプル。

package org.waman.sample.annotation;

@OnType
public enum SexType {
    @OnField MALE,
    @OnField FEMALE   
}

列挙型の要素(フィールド)に @OnField アノテーションを付加することができます。 コンストラクタやメソッドを定義すれば、それらにアノテーションを付加することもできるかと。

アノテーションを用いたサンプル★

アノテーションを用いたサンプル。 定義したアノテーションを使用する際に引数にするもの(以下のサンプルでの value)は、アノテーション定義ではメソッドとして宣言するので @OnMethod アノテーションを付加することができます。

package org.waman.sample.annotation;

@OnAnnotation
public @interface MyAnnotation {
    @OnMethod String value();
}

★パッケージ・アノテーション

パッケージ・アノテーションは、定義の仕方は他のアノテーションと同じですが、アノテーションの付加の仕方が他と少々違っています。 といってもそんなに難しくはなく、アノテーションを付加したいパッケージ・フォルダ上に「package-info.java」というファイルを作成し、そこに以下のような「パッケージ宣言」を書きます:

@OnPackage package org.waman.sample.annotation;

正直、使ったことありませんけど。

*1:インターフェースに定義するフィールドが immutable でないのはまずいコーディングですが、ここではあまり気にしないで下さい:-)