java - 查找被注释处理覆盖的方法
问题描述
代码结构
假设我们有这样的结构:
class A {
@AMethodAnnotation("my-data")
public void myMethod() {
}
}
@MyClassAnnotation
class B extends A {
@Override
public void myMethod() {
}
}
我想要达到的目标
使用注释处理我试图从AMethodAnnotation
位于myMethod
class 内部方法上的注释中提取数据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
is的超类A
并遍历enclosedElements
in A
,然后您必须验证方法名称是否相同,以及参数是否相同且顺序相同。但我发现这种方法需要大量检查,因此我的问题是是否有更好的方法。
解决方案
我根据评论中发布的链接@rmuller 编写了以下方法。如 Javadoc 和下图所示,此方法有大量文档,其中更具可读性。
/**
* 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);
}
推荐阅读
- typescript - 根据 TypeScript 中的参数动态生成返回类型
- android - 我在 firebase 控制台中看不到 android 的崩溃报告
- camera-calibration - 使用 HALCON 进行 3D 三角测量
- visual-studio-code - 在 VSCode 上美化 c++ 文件
- ruby-on-rails - OmniAuth::Strategies::OAuth2::CallbackError 发生
- javascript - Fullcalendar - 固定宽度事件:左对齐
- python - 如何仅获取父类对象的属性
- ios - 有没有办法从我的主类连接或访问我的“scrollView”到另一个类?
- java - OpenCV 4.1.0 Java:尝试将 BFMatcher 与基于 ORB 的关键点和描述符一起使用时如何修复“未知异常”?
- reactjs - TypeScript 和 React JS 访问 DOM 元素