【问题标题】:How to get field's type annotation in Java Annotation Processing?如何在 Java 注释处理中获取字段的类型注释?
【发布时间】:2014-07-10 07:02:26
【问题描述】:

例如,我有这样的代码:

@Retention(RetentionPolicy.SOURCE)
public @interface ClassAnnotation {
}

@ClassAnnotation
public class AnnotatedClass {
}

@ClassAnnotation
public class AnotherAnnotatedClass {

    private AnnotatedClass someField;
    private int intIsNotAnnotated;
}

这个处理器在编译时对其进行预处理:

@SupportedAnnotationTypes({ "com.example.ClassAnnotation" })
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class AwesomeProcessor extends AbstractProcessor {

    public boolean process(Set<? extends TypeElement> annotations,
            RoundEnvironment roundEnv) {
        // Skipped for brevity...
        // For each annotated class
        for (Element e : roundEnv.getElementsAnnotatedWith(ClassAnnotation.class)) {
            // Skipped for brevity...
            // For each field
            for (Element ee : classElement.getEnclosedElements()) {
                // Skipped for brevity... (of course there's kind checking)
                TypeMirror fieldType = fieldElement.asType();
                TypeElement fieldTypeElement = (TypeElement) processingEnv.
                    getTypeUtils().asElement(fieldType);
            }
        }
        // Skipped for brevity
    }
}

我需要检查一个字段的类型是否是一个用我的注解注解的类。不知何故,我有一个名为fieldTypeElementTypeElement,它可能代表来自someFieldAnnotatedClass 或来自示例中的intIsNotAnnotatedint。如何获得@ClassAnnotationAnnotatedClasssomeField?我试过fieldTypeElement.getAnnotation(ClassAnnotation.class)fieldTypeElement.getAnnotationMirrors(),但它分别返回null和空列表。

【问题讨论】:

    标签: java annotations preprocessor annotation-processing


    【解决方案1】:

    我认为您在某种程度上弄错了TypeElement,但不幸的是,这部分代码丢失了。

    这个简单的例子按预期工作:

    processingEnv.getElementUtils().getTypeElement("AnnotatedClass").getAnnotationMirrors()
    

    包含@ClassAnnotation

    要获得字段的TypeElement,您必须

    1. 获取字段类型
    2. 将类型转换为DeclaredType
    3. 获取声明类型的元素
    4. 将元素转换为TypeElement

    最后一步并不是获取元素注释的必要步骤:

    Element field = // ... 
    List<? extends AnnotationMirror> annotationMirrors =
        ((DeclaredType) field.asType()).asElement().getAnnotationMirrors();
    

    更新后的代码应该可以工作,我已经对其进行了测试,并且运行良好。错误必须在其他地方。其他需要检查的事项:

    • 确保构建良好,有时构建步骤会失败并且旧代码被使用而不引起注意
    • 检查注解的RetentionPolicy。无,CLASSRUNTIME 都可以,但 SOURCE 不起作用

    【讨论】:

    • 我添加了更多代码来展示我如何在我的问题中得到TypeElement
    • @BornToCode 我已经更新了答案。如果它仍然不起作用,我现在没有想法。
    • 哦,你是对的。我使用了SOURCE 保留。问题已更新以显示保留政策。但我仍然很好奇为什么它不起作用,注释处理是在 source 阶段而不是 runtime 阶段,不是吗?
    • @BornToCode 您仍然可以在注释处理发生时访问源文件,但是在使用 java.lang.model api 时,您已经有了源代码的更抽象表示。我认为 source 仅适用于编译器(或任何读取原始源文件的东西)。
    【解决方案2】:

    遍历Class上的Fields,检查每个字段的类型是否包含注解。要获取Field 的类型,请使用Field#getType 方法。从提供的伪代码看来,您可以访问Fields。

    Processor.java

    public class Processor {
    
        public static void main(String[] args) {
    
            Class<?> clazz = AnotherAnnotatedClass.class;
            Field[] fields = clazz.getDeclaredFields();
    
            for(Field f:fields){
                if(f.getType().isAnnotationPresent(ClassAnnotation.class)){
                    System.out.println(f.getName());
                }
            }
        }
    }
    

    ClassAnnotation.java

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface ClassAnnotation {
    
    }
    

    AnnotatedClass.java

    @ClassAnnotation
    public class AnnotatedClass {
    
    }
    

    AnotherAnnotatedClass.java

    @ClassAnnotation
    public class AnotherAnnotatedClass {
    
        private AnnotatedClass annotatedClass;
        private int intIsNotAnnotated;
    }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-20
    • 2013-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 1970-01-01
    相关资源
    最近更新 更多