Java 如何在注释处理中获取泛型类型的限定类名?
我有这样一个界面:Java 如何在注释处理中获取泛型类型的限定类名?,java,annotation-processing,Java,Annotation Processing,我有这样一个界面: interface MyInterface<V>{ } 我有类1、2和3的TypeElements,我想找到类型变量V的限定名 我尝试了这个方法,但它返回的是V,而不是SomeClass TypeElement class1 = ... while(reachToMyInterface){ for (TypeMirror m : ((DeclaredType) class1.asType()).getTypeArguments()) { print
interface MyInterface<V>{
}
我有类1、2和3的TypeElement
s,我想找到类型变量V
的限定名
我尝试了这个方法,但它返回的是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> {}
要做到这一点需要进行大量的测试和修改,我使用此测试来调试流程:
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);
}
}
公共类ProcTest{
@试验
公开募捐{
字符串basePath=“/path/to/src/folder/”;
List args=asList(“哈哈”,“我的接口”,“StringImpl”)
.stream()
.map(s->basePath+“bar/”+s+“.java”)
.collect(Collectors.toList());
args.addAll(0,asList(“-processor”,Proc.class.getName());
String[]flags=args.toArray(新字符串[3]);
ToolProvider.getSystemJavaCompiler()
.run(System.in、System.out、System.err、标志);
}
}
如果在调试模式下运行,则可以在注释处理器内设置断点。这确实帮助我更好地理解事物。@jornverne如果
MyInterface
有一个方法void foo(V bar)
,那么有可能获得MyClass
?我仍然对第二种方法感到困惑,因为Class2可能没有覆盖foo
@jornverne注释处理发生在编译时,而不是运行时。您的语句在运行时也是错误的。实例类型被删除,但类、方法和字段中的类型边界被保留。查询这些信息是一门非常高级的学科。这里讨论的是:谢谢,但是第二条路或者第三条路呢?@SaeedMasoumi我给了你一个起点。如果我获取每个元素的所有祖先并获取它们接口的类型参数System.out.println(参数),那么您将从中找到答案
将打印V
而不是SomeClass
,那么您必须创建一些代码,将这种逻辑递归地应用于超类和扩展接口。我知道,我已经尝试过您的方法,但对祖先不起作用。请看我编辑的问题
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);
}
}