アノテーションの理解、活用方法と独自アノテーションの作成

  1. アノテーションの基礎知識

1. アノテーションとは?

厳密に言えば、アノテーションはコメントのようなメタデータをプログラム要素(クラス、メソッド、フィールドなど)に関連付けるための安全な仕組みです。これにより、アプリケーションのロジックとは関係のない情報を追加し、特定のツールやフレームワークが利用できるようになります。アノテーションは修飾子のように、パッケージ、型、コンストラクタ、メソッド、フィールド、パラメータ、ローカル変数などの宣言に使用できます。 Javaにおけるアノテーションは、コード内に埋め込まれたメタデータであり、コンパイル時や実行時に解析・利用されるために存在します。実際のロジックには影響を与えず、補助的な役割のみを果たします。アノテーションはjava.lang.annotationパッケージに含まれます。 以下のように定義されます:

アノテーション(Annotation)は、コードレベルでの説明として機能するものです。JDK1.5以降で導入された機能で、クラスやインターフェース、列挙体と同じ階層に位置します。パッケージ、クラス、フィールド、メソッド、ローカル変数、パラメータなどに付与され、これらの要素についての情報を提供します。 — 百度百科より

2. アノテーションの主な用途

  1. 他者が書いたコード(特にフレームワーク関連)を読み解くこと;

  2. 設定ファイルによる記述を置き換える機能。複雑な設定やロジックが必要だった場合でも、適切なアノテーションを使用することで、簡潔な記述で同等の処理が可能です。コードの可読性と整理が向上します;

  3. コンパイル時の形式チェック。

  4. メタアノテーション


メタアノテーションとは、他のアノテーションに付与されるアノテーションのことです。つまり、基本的なアノテーションでありながら、他の通常のアノテーションに適用可能な特殊なラベルです。これは、他のラベルに対して意味を説明するためのものです。

主なメタアノテーションには@Retention、@Documented、@Target、@Inheritedの4つがあり(Java 8ではさらに@Repeatableも追加されました)。

2.1 @Retention

@Retentionはアノテーションのライフサイクルを定義します。このアノテーションが適用された場合、そのアノテーションの保持期間が決まります。

RetentionPolicy.SOURCE: ソースコード段階でのみ保持され、コンパイル後は無視されます。 例:@Override、@SuppressWarnings RetentionPolicy.CLASS: コンパイル段階まで保持されますが、JVMにロードされることはありません。 RetentionPolicy.RUNTIME: 実行時まで保持され、JVMにロードされるため、実行中に取得できます。多くの場合、アノテーションはRUNTIMEで定義されています。

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {
    String value() default "";
}

2.2 @Target

@Targetは、アノテーションがどこに適用できるかを指定します。具体的には、アノテーションが使用できる要素を制限します。使用可能なElementTypeパラメータは以下の通りです:

ElementType.CONSTRUCTOR: コンストラクタに適用; ElementType.ANNOTATION_TYPE: アノテーションに適用; ElementType.FIELD: フィールドやメンバ変数、enumインスタンスに適用; ElementType.LOCAL_VARIABLE: ローカル変数に適用; ElementType.METHOD: メソッドに適用; ElementType.PACKAGE: パッケージに適用; ElementType.PARAMETER: パラメータに適用; ElementType.TYPE: クラス、インタフェース、列挙体に適用;

2.3 @Documented

@Documentedは、アノテーションの情報をJavaドキュメント(Javadoc)に含めるかどうかを示す単純なマーカーです。

2.4 @Inherited

Inheritedは継承を意味し、@Inheritedアノテーションがクラスに付与された場合、そのクラスを継承したサブクラスがアノテーションを明示的に指定しなかった場合でも、親クラスのアノテーションを引き継ぐことができます。

  1. 独自アノテーションの作成

独自アノテーションを作成する際の規則:

アノテーションの型は@interfaceとして定義します。すべてのアノテーションはjava.lang.Annotationインターフェースを暗黙的に継承しており、他のクラスやインターフェースを継承することはできません; パラメータメンバーはpublicまたはdefaultのみを修飾子として使用できます; パラメータメンバーには基本型(byte, short, char, int, long, float, double, boolean)、String、Enum、Class、Annotations、およびそれらの配列のみを使用できます; アノテーション情報を取得するには、Javaのリフレクション機能を使用する必要があります; メンバー変数を持たないアノテーションはほとんど意味がありません; 独自アノテーションはメタアノテーションを使用して作成する必要があります;

/**
* 果物名を表すアノテーション
*/
@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface FruitName {
String value() default "";
}

/**
* 果物の色を表すアノテーション
*/
@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface FruitColor {
/**
* 色の列挙型
*/
public enum Color{ BLUE,RED,GREEN};

/**
* 色の属性
*/
Color fruitColor() default Color.GREEN;
}

/**
* 果物の供給者を表すアノテーション
*/
@Target(FIELD)
@Retention(RUNTIME)
@Documented
public @interface FruitProvider {
/**
* 供給者ID
*/
public int id() default -1;

/**
* 供給者名
*/
public String name() default "";

/**
* 供給者住所
*/
public String address() default "";
}

/**
* アノテーション処理クラス
*/
public class FruitInfoUtil {
public static void getFruitInfo(Class clazz){

String strFruitName=" 果物名:";
String strFruitColor=" 果物の色:";
String strFruitProvicer="供給者情報:";

Field[] fields = clazz.getDeclaredFields();

for(Field field :fields){
if(field.isAnnotationPresent(FruitName.class)){
FruitName fruitName = (FruitName) field.getAnnotation(FruitName.class);
strFruitName=strFruitName+fruitName.value();
System.out.println(strFruitName);
}
else if(field.isAnnotationPresent(FruitColor.class)){
FruitColor fruitColor= (FruitColor) field.getAnnotation(FruitColor.class);
strFruitColor=strFruitColor+fruitColor.fruitColor().toString();
System.out.println(strFruitColor);
}
else if(field.isAnnotationPresent(FruitProvider.class)){
FruitProvider fruitProvider= (FruitProvider) field.getAnnotation(FruitProvider.class);
strFruitProvicer=" 供給者ID:"+fruitProvider.id()+" 供給者名:"+fruitProvider.name()+" 供給者住所:"+fruitProvider.address();
System.out.println(strFruitProvicer);
}
}
}
}

/**
* アノテーションの使用例
*/
public class Apple {

@FruitName("Apple")
private String appleName;

@FruitColor(fruitColor = FruitColor.Color.RED)
private String appleColor;

@FruitProvider(id=1,name="陝西紅富士グループ",address="陝西省西安巿延安路89番地紅富士ビル")
private String appleProvider;

public void setAppleColor(String appleColor) {
this.appleColor = appleColor;
}
public String getAppleColor() {
return appleColor;
}

public void setAppleName(String appleName) {
this.appleName = appleName;
}
public String getAppleName() {
return appleName;
}

public void setAppleProvider(String appleProvider) {
this.appleProvider = appleProvider;
}
public String getAppleProvider() {
return appleProvider;
}

public void displayName(){
System.out.println("果物の名前は:リンゴ");
}
}

タグ: Java アノテーション メタアノテーション リフレクション カスタムアノテーション

7月2日 20:52 投稿