获取枚举类型变量的注释

39

我有一些非null的变量(例如en1),其类型为Enum。问题是:如何获取与被en1变量引用的枚举常量相关的注释?


我不确定你想要实现什么。是这样的 Object en1 = ...; Annotation[] anns = magic(en1); 吗?那我会问为什么 en1Object 类型而不是 En 类型。你能提供一些类似的示例代码吗? - musiKk
3
我已经找到了正确的答案。它是:en1.getClass().getField(((Enum)en1).name()).getAnnotations(); - Timofey Gorshkov
@musiKk:抱歉,我的说法“en1 是某个 enum 类型”是指 en1Enum 的一个实例。 - Timofey Gorshkov
5个回答

40

试试这个(使用Java反射):

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

这应该可以帮助你获取来自AAA的注解。

编辑:

正如作者所假设的:

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

对他有效 :)


9
使用.name()比使用.toString()更安全,因为toString()可能被重载(而name()final)。 - Joachim Sauer
你的答案并不完整,因为我无法确定En常量中哪个被赋予了en1。此外,在你回答之前我已经编辑了我的问题并加强了要求。 - Timofey Gorshkov
但是它不起作用,是吗?似乎总是返回一个空数组。而且 isAnnotationPresent() 总是返回 false - rds
3
请确保在你的@interface上使用@Retention(RetentionPolicy.RUNTIME)。意思是让注解在运行时仍然可用。 - MightyE

23

我已经提供过了:

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的真实类别。
另请参阅:有关混淆案例的说明

1
似乎是8小时前的相同答案。 - vinnyjames

7

我看到你的评论已经找到了答案。我只是想提醒其他感兴趣的人,在这种情况下,为了使其生效,这些注释必须已经使用正确的保留策略进行声明,例如:

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

如果没有这个,它们将无法在运行时访问。

更多阅读:


还应该注意,如果存在@Target注释,则其中至少应该有ElementType.FIELD - Timofey Gorshkov

5

如果您正在使用类似于Proguard的混淆器,则可能会发现枚举字段已被重命名,而.name()仍然返回该字段的原始名称。例如,此枚举...

enum En {
    FOO,
    BAR
}

经过ProGuard处理后,它会变成这样...

enum En {
    a,
    b
}

然而En.FOO.name()仍将返回"FOO",导致getField(En.FOO.name())失败,因为它期望该字段的名称为"a"

如果您想从混淆代码中获取特定枚举字段的Field,可以执行以下操作:

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

2

根据现有的答案,如果您控制枚举类(可以编辑它),您可以简单地添加一个方法到枚举中来获取所需的注释,例如:

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)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接