java - 查找被注释处理覆盖的方法

标签 java annotations annotation-processing annotation-processor

代码结构

假设我们有这样的结构:

class A {

    @AMethodAnnotation("my-data")
    public void myMethod() {

    }

}

@MyClassAnnotation
class B extends A {

    @Override
    public void myMethod() {

    }

}

我想要实现的目标

使用注释处理,我尝试从注释 AMethodAnnotation 中提取数据位于方法 myMethod类内A 。类B扩展此类并覆盖其方法 myMethod .

不同之处在于我想要来自 AMethodAnnotation 的方法的数据如果它所在的类有注释 MyClassAnnotation .

我正在获取带注释的类 MyClassAnnotation并循环 enclosedElements ,我可以检查它是否有 Override注释,但我不确定如何获取它覆盖的方法,因为那是 AMethodAnnotation 的位置位于我想要的数据中。 ExecutableElement似乎没有提供获取此信息的方法。

for (Element classElement : roundEnv.getElementsAnnotatedWith(MyClassAnnotation.class)) {
    // Make sure it's a class
    if (classElement.getKind() != ElementKind.CLASS) {
        continue;
    }

    // Loop through methods inside class
    for (Element methodElement : classElement.getEnclosedElements()) {
        // Make sure the element is a method & has a @Path annotation
        if (methodElement.getKind() != ElementKind.METHOD) {
            continue;
        }

        // If method has @Override annotation do stuff

    }
}

问题

有没有办法获得对被覆盖的方法的引用?

有一种方法,你可以得到 B 的父类(super class)这是 A然后你循环遍历 enclosedElementsA ,那么你必须验证方法名称是否相同,参数是否相同且顺序相同。但我发现这种方法需要大量检查,因此我想知道是否有更好的方法。

最佳答案

我根据评论中发布的链接@rmuller 编写了以下方法。此方法有大量文档,如 Javadoc 和下图所示,其中的可读性更强。

The Javadoc as formatted by eclipse, so its actually readable

/**
 * Will find the method which the method <strong>methodElement</strong> is overriding, if any.
 * It does this by recursively traversing up the superclass tree of the
 * <strong>classElement</strong> and checking if there are methods which override the
 * <strong>methodElement</strong>. It will return after it finds the first method with the
 * annotation <strong>annotation</strong>.
 *
 * @param originalClassElement The original class inside which the
 *                             <strong>methodElement</strong> is located.
 * @param classElement         The class which represents the superclass while recursively
 *                             looking up the tree, it should be equal to the
 *                             <strong>originalClassElement</strong> when first calling this
 *                             method.
 * @param methodElement        The method for which should be checked if it's overriding
 *                             anything.
 * @param annotation           The annotation which must be matched before returning the result
 * @return Will return the following, the list is written in order:
 *         <ul>
 *         <li>The method <strong>methodElement</strong> if <strong>methodElement</strong>
 *         already has an annotation of the type <strong>annotation</strong></li>
 *         <li>Null if the method <strong>methodElement</strong> does not have an @Override
 *         annotation</li>
 *         <li>Null if the class <strong>classElement</strong> does not have a superclass</li>
 *         <li>The method element which was found to have the annotation
 *         <strong>annotation</strong></li>
 *         </ul>
 */
public ExecutableElement getMethodOverride(TypeElement originalClassElement,
        TypeElement classElement, ExecutableElement methodElement,
        Class<? extends Annotation> annotation) {

    if (methodElement.getAnnotation(annotation) != null) {
        // The methodElement which was passed has the required annotation already
        return methodElement;
    }

    if (methodElement.getAnnotation(Override.class) == null) {
        // The methodElement which was passed does not have an @Override annotation and is
        // therefore not overriding anything.
        return null;
    }

    if (classElement.getSuperclass().getKind() == TypeKind.NONE) {
        // Class has no superclass
        return null;
    }

    for (Element elem : classElement.getEnclosedElements()) {
        if (elem.getKind() != ElementKind.METHOD) {
            // Not a method
            continue;
        }

        // Check if the method inside the superclass overrids the method inside the original
        // class
        if (this.processingEnv.getElementUtils().overrides(methodElement,
                (ExecutableElement) elem, classElement)) {

            // Recursively go up the tree and check since this method might also override
            // another method
            return getMethodOverride(originalClassElement,
                    this.env.getElementUtils()
                            .getTypeElement(classElement.getSuperclass().toString()),
                    (ExecutableElement) elem, annotation);
        }

    }

    // Recursively go up the tree and check there
    return getMethodOverride(originalClassElement,
            this.env.getElementUtils().getTypeElement(classElement.getSuperclass().toString()),
            methodElement, annotation);
}

关于java - 查找被注释处理覆盖的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53105371/

相关文章:

java - 将标准输入中的多个 JPG 合并为多文件 TIFF

Hibernate spring 注释 session 未关闭/刷新

annotations - 如何在注解 Kotlin 中使用类

java - 如何在 Gradle 中使用自定义 Java Annotation Processor?

java - 如何找到 ExecutableElement 的类名?

java - 优雅地处理 TypeMirror 和 Class

java - 如何从单个列表中挑选独特的对

java - Java 中的回文 int

java - 如何从 Servlet 输出文本到控制台

如果不满足条件则忽略方法调用的 Java 注释