web-dev-qa-db-ja.com

コンストラクターに渡された特定のオブジェクト内の現在の注釈を検出する

簡単に言えば、特定のユーザークラス/オブジェクトに対してJavaアノテーションが(適切な場所に)存在するかどうかを検出するにはどうすればよいですか。

「問題」の詳細

2つのJavaクラスがあります:

public class Line {
   private List<Cell> cells;

   public Line(Object... annotatedObjects) {
     // check if annotations @Line and @Cell are present in annotatedObjects.
   }

   // getter/setter for cells.
}

public class Cell {
   // some members
   // some methods
}

Lineオブジェクトはセルを保持します。

次のような2つの注釈もあります。

public @interface Line {
  // some stuff here
}

public @interface Cell {
  // some stuff here
}

また、次のように、指定した@Lineアノテーションと@Cellアノテーションを含む多数のユーザークラス(この例では2つ)があります。

@Line(name="pqr", schema="three")
public class AUserClass {
   @Cell
   private String aString;
}

@Line(name="xyz", schema="four")
public class AnotherUserClass {
   @Cell(name="birthday")
   private Date aDate;
}

問題:新しいLineオブジェクトをインスタンス化するときに、ユーザークラス/オブジェクトをLineコンストラクターに渡すことができるようにします。 Lineコンストラクターは、渡されたユーザークラス/オブジェクトが処理可能な有効なクラスであるかどうかを確認します。クラスの@Line注釈と、そのメンバーの少なくとも1つの@Cell注釈を持つユーザークラスのみが、Lineオブジェクトのコンストラクターに渡すことができる有効なオブジェクトです。他のすべての渡されたオブジェクトは無効です。有効なユーザーオブジェクトが渡されると、そのオブジェクトで@Cellとしてタグ付けされている使用可能なすべてのメンバーがCellオブジェクトに変換され、セルリストに追加されます。

私の質問:

  1. 実行時にこのオブジェクト/クラスの注釈を検出することは可能ですか?これは渡されたこのオブジェクトに対してのみです(クラスパス上の注釈をスキャンしたくない!)?
  2. @Cellタグ付きメンバーのデータ型を検出することは可能ですか? Cellクラスはすべてのデータ型を受け入れないため、これが必要です。
  3. ユーザーがメンバーのセル名を指定する必要がないように、実際のメンバー名(Javaファイルで指定))を取得することは可能ですか?ユーザーが@Cellを書きたい(名前なし)および@Cell(name="aName")で、@Cellのみが指定されている場合は、代わりにメンバーの名前が使用されます。
  4. 注釈が適切な場所にあるかどうかを検出する方法。このようにコードにタグが付けられている場合、オブジェクトは無視する必要があります(または例外がスローされる可能性があります)?
    @Cell // oh oh, that's no good :(
    public class WrongClass {
    // some members
    }
  5. いくつかのスタートアップコードを提供してもらえますか?私はアノテーションとリフレクションに本当に新しいです。ところで:私は最新のjvm 1.6+を使用しています

ご協力ありがとうございました!

30
user504342

まず、リフレクションでそれらを読むことができるように、アノテーションに保持ポリシーを設定する必要があります

_  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface Line {

  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  public static @interface Cell {

  }
_

次に、クラスにisAnnotationPresent(annotationClass)のLine注釈があるかどうかをテストする必要があります。このメソッドには、_Java.lang.Class_およびJava.lang.reflect.Fieldからアクセスできます。

[〜#〜] note [〜#〜]class.getDeclaredField(fieldName)でプライベートなフィールドを取得する必要があること。

_3._ propertyNameに基づいて注釈にデフォルト値を持たせることはできないと思いますが、デフォルトのString name() default DEFAULTを指定して名前をオプションにし、フィールドを反復処理するときにその値を確認できますname()またはpropertyNameに保存されている値を使用します

43
Liviu T.

Q.1:実行時にこのオブジェクト/クラスの注釈を検出することは可能ですか?これは渡されたオブジェクトのみです(クラスパスで注釈をスキャンしたくない!)?

はい isAnnotationPresent を使用して非常に可能です

@Deprecated
public class AnnotationDetection {

    public static void main(String[] args) {
        AnnotationDetection annotationDetection = new AnnotationDetection();
        System.out.println(annotationDetection.getClass().isAnnotationPresent(Deprecated.class));
    }
}

Runtime で保持するスコープの注釈のみが利用可能です。

20
Jigar Joshi