web-dev-qa-db-ja.com

列挙型変数の注釈を取得する

null タイプの非Enum変数(例:en1)があります。問題は、en1変数によって参照される列挙定数に関連する注釈を取得する方法ですか?

36

私がすでに提供したように:

en1.getClass().getField(((Enum)en1).name()).getAnnotations();

明確にするために:

String name = e.name(); // Enum method to get name of presented enum constant
Annotation[] annos = e.getClass().getField(name).getAnnotations(); // Classical reflection technique

この場合、en1の実際のクラスを知る必要はありません。

参照: 難読化されたケースに関する注意

21

これを試してください(Javaリフレクション):

String field = En.AAA.name();
En.class.getField(field).getAnnotations();

AAAからアノテーションを取得する必要があります。

編集:

著者が想定したように:

en1.getClass().getField(((Enum)en1).name()).getAnnotations(); 

彼のために働く:)

36
Tobias

私はあなたがすでに答えを見つけたというあなたのコメントから読んだだけです。それが機能するためには、これらのアノテーションが次のような正しい保持ポリシーで宣言されている必要があることに関心のある他の人々に注意したいと思います。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Anno1 {
   // ...
}

これがないと、実行時にアクセスできません。

参考文献:

7
Riccardo T.

Proguardなどの難読化ツールを使用している場合、列挙型フィールドの名前が変更されているのに、.name()はフィールドの元の名前を返す場合があります。たとえば、この列挙型...

_enum En {
    FOO,
    BAR
}
_

... ProGuardingの後でこれになります...

_enum En {
    a,
    b
}
_

...ただし、En.FOO.name()は引き続き_"FOO"_を返し、フィールドの名前が_"a"_であると想定しているため、getField(En.FOO.name())は失敗します。

難読化されたコードから特定の列挙型フィールドのFieldを取得する場合は、次のようにします。

_for (Field field : En.class.getDeclaredFields()) {
    if (field.isEnumConstant()) {
        try {
            if (en1 == field.get(null)) {
                Annotation[] annotations = field.getAnnotations();
            }
        } catch (IllegalAccessException e) {
            // 
        }
    }
}
_
4
Jarett Millard

既存の回答に加えて、enumクラスを制御している(編集できる)場合は、enumにメソッドを追加するだけで、必要な注釈をフェッチできます。

AnnotationClass getAnnotation(){
   Field field = this.getClass().getField(this.name());
   return field.getAnnotation(AnnotationClass.class);       
}

またはすべての注釈:

Annotation[] getAnnotations(){
   Field field = this.getClass().getField(this.name());
   return field.getAnnotations();
}

上記のコードを調整して、例外(NoSuchFieldExceptionおよびSecurityException)を処理します。

2
Emmanuel