我有一个注释处理器,它接受带注释的类并尝试创建其中的一个子类:
package test;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeSpec;
import java.io.IOException;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
@SupportedAnnotationTypes("java.lang.SuppressWarnings")
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class BSProcessor extends AbstractProcessor {
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
for (TypeElement baseClassAnnotation : annotations) {
for (Element annotatedElement : roundEnvironment.getElementsAnnotatedWith(baseClassAnnotation)) {
handleAnnotatedTypeElement((TypeElement) annotatedElement);
}
}
return true;
}
private void handleAnnotatedTypeElement(TypeElement annotatedTypeElement) {
try {
javaFile(annotatedTypeElement).writeTo(System.out);
} catch (IOException e) {
e.printStackTrace();
}
}
private JavaFile javaFile(TypeElement annotatedTypeElement) {
return JavaFile.builder(packageName(annotatedTypeElement), typeSpec(annotatedTypeElement))
.build();
}
private TypeSpec typeSpec(TypeElement annotatedTypeElement) {
return TypeSpec.classBuilder(className(annotatedTypeElement))
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.build();
}
private ClassName className(TypeElement annotatedTypeElement) {
return ClassName.get(packageName(annotatedTypeElement), String.format("AutoGenerated_%s",
annotatedTypeElement.getSimpleName()));
}
private String packageName(TypeElement annotatedTypeElement) {
return annotatedTypeElement.getEnclosingElement().toString();
}
}这适用于没有类型参数的类,但我不知道如何处理它们。对类型变量执行toString只会给出变量名,而不是边界。对怎么做有什么想法吗?
发布于 2016-11-15 08:01:41
TypeElement的类型参数可以通过调用getTypeParameters()来检索,它们的边界可以通过对已获得的TypeParameterElements调用getBounds()来获得。我假设您对下面的步骤感到困扰--应该将哪些具体类型传递给这些类型参数以满足这些边界。
不幸的是,这是一个问题,对于任意类型(这就是您所追求的)来说,这是很难解决的。例如,查看这种类型:
public abstract class Recursive<UU extends Callable<UU>> {
}您可以直觉地得出结论,它可以由这样的类实现:
public class Solution extends Recursive<Solution> implements Callable<Solution> {
@Override
public Solution call() throws Exception {
return new Solution();
}
}但是这并不容易自动化,而且您(可能)不希望在代码中包括所需的机器。
我建议您利用类型擦除的优势,让编译器为您解决问题,而不是自己尝试解决这个问题:
// returns something like "Map<K, V>", this is NOT what you want!
DeclaredType classType = (DeclaredType) typeElement.asType();
Types types = processingEnvironment.getTypeUtils();
Elements elements = processingEnvironment.getElementUtils();
// this obtains raw type (plain "Map"), with all methods type-erased,
// the compiler is much better at solving type riddles than you!
DeclaredType rawType = types.getDeclaredType(typeElement);
final Collection<? extends ExecutableElement> methods =
ElementFilter.methodsIn(elements.getAllMembers(typeElement));
// To create a MethodSpec, suitable for the raw type, you should
// call 3-parameter MethodSpec#overriding with type-erased raw class type
// as second parameter and javax.lang.model.util.Types instance as third
MethodSpec newMethod = MethodSpec.overriding(methods.get(0), rawType, types);因此,您的具体问题的答案是“不要将任何类型参数传递给JavaPoet,使用原始类型”。
https://stackoverflow.com/questions/40586423
复制相似问题