JAVAアノテーション:構文の概要と独自のアノテーションの作成

この記事は、初心者、または言語でこのメカニズムをまだ使用していない人に焦点を当てています。 それが何であるのか、なぜ必要なのか、自分にとって便利な注釈を作成する方法を説明しようと思います。



注釈は、プログラムテキストに含まれる記述子であり、プログラムライフサイクルのさまざまな段階で必要なプログラムコードのメタデータを格納するために使用されます。

注釈に保存された情報は、適切なハンドラーが必要な補助ファイルを作成したり、クラス、フィールドなどにマークを付けたりするために使用できます。



構文


注釈は、対応するインターフェースの説明によって定義されます。

たとえば、次のように:



import java.lang.annotation.*; @Target(value=ElementType.FIELD) @Retention(value= RetentionPolicy.RUNTIME) public @interface Name { String name(); String type() defaultstring; }
      
      







上記の例からわかるように、注釈はinterfaceキーワードを使用した説明によって定義され、必須またはオプションのいずれかに設定できるいくつかのフィールドを含めることができます。 後者の場合、フィールドのデフォルト値が置き換えられます。

この例から、注釈自体に複数の注釈を付けることができることもわかります。

独自の注釈をマークする方法とその理由から始めましょう。



@Retentionアノテーションを使用すると、アノテーションのライフサイクルを指定できます 。これは、ソースコード、コンパイル済みファイル、または実行時にも表示されます。 必要なタイプの選択は、注釈の使用方法によって異なります。たとえば、ソースコードから二次的なものを生成したり、実行中にリフレクションを通じてクラスをノックしたりします。



@Targetアノテーションは、このアノテーションで正確にマークできるものを示します。フィールド、メソッド、タイプなどです。



@Documented注釈は、そのようにマークされた注釈をフィールド/メソッドなどのjavadocに追加する必要があることを示します。

たとえば、@ Documentedのないアノテーションでマークされたクラスは次のようになります。

 public class TestClass extends java.lang.Object
      
      







そして、アノテーションの説明に@Documentedを追加すると、次のようになります:

 @ControlledObject(name="name") public class TestClass extends java.lang.Object
      
      







@Inheritedアノテーションは、そのアノテーションでマークされたクラスの子孫によって継承されるアノテーションをマークします。

例としていくつかの注釈を作成し、クラスでマークしてみましょう。



 @Inherited @interface PublicAnnotate { } @interface PrivateAnnotate { } @PublicAnnotate @PrivateAnnotate class ParentClass { } class ChildClass extends ParentClass { }
      
      





ChildClassクラスは、PublicAnnotateアノテーションのみを親クラスから継承します。



注釈の例。


それでは、アノテーションを使用して実際の例を作成してみましょう。

このクラスのオブジェクトのライフサイクルをプロジェクトが制御できるように、入力に特別に注釈が付けられたクラスを受け取る何らかの自作のプロジェクトがあり、StartObject、クラスメソッドを説明するStopObjectアノテーション、および自身を説明するControlledObjectがあるとしますクラス。 最後の注釈に名前フィールド、おそらく検索の名前があるパスを指定します。

注釈は次のようになります。



 @Target(value=ElementType.METHOD) @Retention(value= RetentionPolicy.RUNTIME) public @interface StartObject { } @Target(value=ElementType.METHOD) @Retention(value= RetentionPolicy.RUNTIME) public @interface StopObject { } @Target(value=ElementType.TYPE) @Retention(value= RetentionPolicy.RUNTIME) public @interface ControlledObject { String name(); }
      
      







クラスが仮想プロジェクトへのロードに適しているかどうかをチェックするモジュールを作成します。

最初に、テストするクラス自体を定義します。



 @ControlledObject(name="biscuits") public class Cookies { @StartObject public void createCookie(){ //  } @StopObject public void stopCookie(){ //  } }
      
      







クラスを操作するには、最初にクラスをアプリケーションコンテキストにロードする必要があります。 私たちは使用します:

Class cl = Class.forName("org.annotate.test.classes.Cookies");





さらに、リフレクションメカニズムを通じて、クラスのフィールドと注釈にアクセスできます。

クラスの注釈付きメソッドとクラス自体の注釈を確認します。



 if(!cl.isAnnotationPresent(ControlledObject.class)){ System.err.println("no annotation"); } else { System.out.println("class annotated ; name - " + cl.getAnnotation(ControlledObject.class)); } boolean hasStart=false; boolean hasStop=false; Method[] method = cl.getMethods(); for(Method md: method){ if(md.isAnnotationPresent(StartObject.class)) {hasStart=true;} if(md.isAnnotationPresent(StopObject.class)) {hasStop=true;} if(hasStart && hasStop){break;} } System.out.println("Start annotaton - " + hasStart + "; Stop annotation - " + hasStop );
      
      







実行すると、次の出力が得られます。

注釈の開始-true; 注釈の停止-true。

いずれかの注釈を削除しようとすると、出力は要件への違反を報告します。



まとめ


注釈がプログラムコードを操作するための十分な機会を提供し、標準言語注釈を使用するだけでなく、ニーズに合わせて注釈を作成することで生活を楽にすることも理にかなっていることを示したと思います。



このメカニズムの詳細については、Kay S. Horstmann、Gary Cornell著の本「Java 2. Professional Library、Volume 2. Programming Subtleties」 、またはオラクルのWebサイトで詳細なチュートリアルを参照してください。



All Articles