如何在注解处理中获取泛型的限定class名称?

How to get the qualified class name of generic type in annotation processing?

我有这样的界面:

interface MyInterface<V>{

}
例如,

以及我所有带有 @MyAnnotation 注释的 class 以不同的方式实现此接口。

//first way
Class1 implement MyInterface<SomeClass>
//second way
AbstractClass<V> implement MyInterface<V>
Class2 extends  AbstractClass<SomeClass>
//third way    
ConcreteClass implement MyInterface<SomeClass>
Class3 extends ConcreteClass

好吧,我有 TypeElement 个 class 1,2 和 3,我想找到类型变量 V.

的合格名称

我试过了,但是 returns V 而不是 SomeClass

TypeElement class1 = ...
while(reachToMyInterface){
for (TypeMirror m : ((DeclaredType) class1.asType()).getTypeArguments()) {
      print(m.toString()) // prints V
  }
  class1 = getItsSuperClass();
}

编辑: 这种方法也有同样的问题:

 for (Element element : roundEnv.getElementsAnnotatedWith(Haha.class)) {
            if (element instanceof TypeElement) {
                TypeElement te = (TypeElement) element;
                TypeElement currentType = te;
                while(currentType!=null){
                for (TypeMirror typeMirror : currentType .getInterfaces()) {
                  if (typeMirror instanceof DeclaredType) {
                       DeclaredType dclt = (DeclaredType) typeMirror;
                      for (TypeMirror argument : dclt.getTypeArguments()) {
                        print(argument);
                      }
                   }
                }
                currentType = getSuperClass(currentType);                   
              }
}
private TypeElement getSuperClass(TypeElement typeElement) {
        if (!(typeElement.getSuperclass() instanceof DeclaredType)) return null;
        DeclaredType declaredAncestor = (DeclaredType) typeElement.getSuperclass();

        return (TypeElement) declaredAncestor.asElement();
    }

这很痛苦,但可以做到。

这些类型:

@Retention(RUNTIME) @Target(TYPE) public @interface Haha {}

interface MyInterface<V>{}

@Haha public class StringImpl implements MyInterface<String> {}

这是一个注释处理器,它为 StringImpl 上的 @Haha 注释打印 "java.lang.String":

public class Proc extends AbstractProcessor {
    @Override public Set<String> getSupportedAnnotationTypes() {
        return Collections.singleton("bar.Haha");
    }

    @Override public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.RELEASE_8;
    }

    @Override public boolean process(final Set<? extends TypeElement> annotations,
                                     final RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getElementsAnnotatedWith(Haha.class)) {
            if (element instanceof TypeElement) {
                TypeElement te = (TypeElement) element;
                for (TypeMirror typeMirror : te.getInterfaces()) {
                    if (typeMirror instanceof DeclaredType) {
                        DeclaredType dclt = (DeclaredType) typeMirror;
                        for (TypeMirror argument : dclt.getTypeArguments()) {
                            System.out.println(argument);
                        }
                    }
                }
            }
        }
        return false;
    }
}

到达那里需要大量的测试和摆弄,我使用这个测试来调试过程:

public class ProcTest {
    @Test
    public void run() {
        String basePath = "/path/to/src/folder/";
        List<String> args = asList("Haha", "MyInterface", "StringImpl")
                .stream()
                .map(s -> basePath +"bar/" + s + ".java")
                .collect(Collectors.toList());
        args.addAll(0, asList("-processor", Proc.class.getName()));
        String[] flags = args.toArray(new String[3]);
        ToolProvider.getSystemJavaCompiler()
                    .run(System.in, System.out, System.err,  flags);
    }
}

如果你在调试模式下运行,你可以在注解处理器中设置断点。这确实帮助我更好地理解了事情。