如何在注解处理中获取泛型的限定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);
}
}
如果你在调试模式下运行,你可以在注解处理器中设置断点。这确实帮助我更好地理解了事情。
我有这样的界面:
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);
}
}
如果你在调试模式下运行,你可以在注解处理器中设置断点。这确实帮助我更好地理解了事情。