注釈の作成は非常に簡単なプロセスですが、いくつかのルールによって制限されます。次に、それらがどのような実際的な目的に役立つのかを理解する必要があります。

独自のアノテーションを作成する方法を思い出してください。

クラスとメソッド用で、コードの作成者とバージョンに関する情報を含むアノテーションを作成します。


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Info {
   String author() default "Author";
   String version() default "0.0";
}

注釈を付けたクラスは次のとおりです。


@Info
public class MyClass1 {
   @Info
   public void myClassMethod() {}
}
 
@Info(version = "2.0")
public class MyClass2 {
   @Info(author = "Anonymous")
   public void myClassMethod() {}
}
 
@Info(author = "Anonymous", version = "2.0")
public class MyClass3 {
   @Info(author = "Anonymous", version = "4.0")
   public void myClassMethod() {}
}

実行時にこのデータをどのように使用できるでしょうか?

リフレクションを使用してアノテーションからメタデータを抽出します。反省とは何かを思い出してください。リフレクションは、実行時にプログラムに関するデータを検査するメカニズムです。リフレクションを使用すると、フィールド、メソッド、クラス コンストラクター、およびクラスに関する情報を取得できます。

リフレクションを使用してクラス内の注釈を読み取り、必要な情報を表示します。

mainメソッドでクラスからデータを読み取ります。


import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
 
public class Main {
   public static void main(String[] args) throws NoSuchMethodException {
       readMyClass(MyClass1.class);
       readMyClass(MyClass2.class);
       readMyClass(MyClass3.class);
   }
 
   static void readMyClass(Class<?> myClassObj) throws NoSuchMethodException {
       System.out.println("\nClass: " + myClassObj.getName());
       readAnnotation(myClassObj);
       Method method = myClassObj.getMethod("myClassMethod");
       readAnnotation(method);
   }
 
   static void readAnnotation(AnnotatedElement element) {
       try {
           System.out.println("Search for annotations in " + element.getClass().getName());
           Annotation[] annotations = element.getAnnotations();
           for (Annotation annotation : annotations) {
               if (annotation instanceof Info) {
                   final Info fileInfo = (Info) annotation;
                   System.out.println("Author: " + fileInfo.author());
                   System.out.println("Version: " + fileInfo.version());
               }
           }
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
}

クラスのインスタンスをreadMyClassメソッドに渡します。

次に、クラスとメソッドをreadAnnotationメソッドに渡すことができます。それでは、Class オブジェクトと Method オブジェクトを渡します。AnnotatedElementインターフェイスを実装するオブジェクトを受け取ります。これにより、オブジェクトから注釈のリストを取得し、それぞれの注釈に関する情報を取得できるようになります。

注釈が注釈タイプif (annotationinstanceof Info)に属しているかどうかを確認した後でのみ情報を取得することに注意してください。

プログラム出力では、注釈からの完全な情報が得られます。

クラス: annotation.MyClass1
java.lang.Class でアノテーションを検索します。
Author: Author
バージョン: 0.0
java.lang.reflect.Method でアノテーションを検索します。
Author: Author
バージョン: 0.0

クラス: annotation.MyClass2
java.lang でアノテーションを検索します。クラス
著者: 著者
バージョン: 2.0
java.lang.reflect.Method でアノテーションを検索
著者: Anonymous
バージョン: 0.0

クラス: annotation.MyClass3
java.lang.Class でアノテーションを検索
著者: Anonymous
バージョン: 2.0
Java でアノテーションを検索します。 lang.reflect.Method
作者: Anonymous
バージョン: 4.0

したがって、リフレクションの助けを借りて、メタデータを抽出することができました。

次に、読みやすさ、速度、品質全般の向上など、コードを改善するためにアノテーションを使用する例を見てみましょう。ロンボク島はこれを手伝ってくれます。

Lombok は、アノテーションを使用して膨大な量のコードを隠し、言語を拡張するコンパイラ プラグインです。これにより、開発が簡素化され、機能が追加されます。

ロンボク島のアノテーションの例を考えてみましょう。

@ToString オブジェクトの完全な表現 (クラス名、すべてのフィールド、およびそれらの値) で構成されるtoString()メソッドの実装を生成します。

@ToString
public class Example
@EqualsAndHashCode デフォルトで非静的フィールドと非静的フィールドを使用する、equalshashCodeの実装を生成しますが、構成可能です。 詳細については、プロジェクトの Web サイトをご覧ください。そこには@EqualsAndHashCodeを使用する例があり、アノテーションのない標準実装も示されています。
@ゲッター/ @セッター プライベートフィールドのゲッターとセッターを生成します。

@Getter 
@Setter 
private String name = "name";
@NonNull オブジェクトがインスタンス化されるときに、フィールドが null ではないことをアサートするために使用されます。それ以外の場合は、NullPointerExceptionがスローされます。

public Example(@NonNull P p) {
 super("Hello");
 this.name = p.getName();
}

ロンボク島には、あまり使用されない便利なアノテーションがたくさんあります。私たちはその最も単純な注釈を検討しました。プロジェクトの詳細については、公式 Web サイトをご覧ください。