【发布时间】:2017-11-15 09:38:13
【问题描述】:
我想使用注解处理器创建一个静态嵌套类。有可能吗?
我创建了@MyAnnotation注解:
package annotationprocessing;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
}
和注释处理器:
package annotationprocessing;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.processing.Filer;
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.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.util.Elements;
import javax.tools.JavaFileObject;
@SupportedAnnotationTypes({"annotationprocessing.MyAnnotation"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class MyAnnotationProcessor extends javax.annotation.processing.AbstractProcessor {
private Filer filerUtils;
private Elements elementUtils;
private TypeElement myAnnotationTypeElement;
private Map<TypeElement, List<VariableElement>> annotatedFields;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
filerUtils = processingEnv.getFiler();
elementUtils = processingEnv.getElementUtils();
myAnnotationTypeElement = elementUtils.getTypeElement(MyAnnotation.class.getCanonicalName());
}
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
annotatedFields = new HashMap<>();
roundEnv.getElementsAnnotatedWith(myAnnotationTypeElement)
.stream()
.map(element -> (VariableElement) element)
.forEach(this::processAnnotation);
if (annotatedFields.isEmpty()) {
return true;
}
System.err.println(annotatedFields);
for (Map.Entry<TypeElement, List<VariableElement>> entry : annotatedFields.entrySet()) {
TypeElement enclosingClass = entry.getKey();
try {
JavaFileObject javaFileObject = filerUtils.createSourceFile(enclosingClass.getQualifiedName().toString() + "$Nested");
try (BufferedWriter writer = new BufferedWriter(javaFileObject.openWriter())) {
if (elementUtils.getPackageOf(enclosingClass).getQualifiedName().length() > 0) {
writer.write("package " + elementUtils.getPackageOf(enclosingClass).getQualifiedName() + ";");
writer.newLine();
}
writer.write("public /*static*/ class " + enclosingClass.getSimpleName() + "$Nested {");
writer.newLine();
for (VariableElement varElement : entry.getValue()) {
writer.write("static int " + varElement.getSimpleName() + ";");
writer.newLine();
}
writer.newLine();
writer.write("}");
}
} catch (IOException ex) {
Logger.getLogger(MyAnnotationProcessor.class.getName()).log(Level.SEVERE, null, ex);
}
}
return true;
}
private void processAnnotation(VariableElement sharedElement) {
TypeElement enclosingClass = (TypeElement) sharedElement.getEnclosingElement();
annotatedFields.putIfAbsent(enclosingClass, new ArrayList<>());
annotatedFields.get(enclosingClass).add(sharedElement);
}
}
编译类时(javac -processor annotationprocessing.MyAnnotationProcessor -cp annotationprocessing.jar TestClass.java)
package org.full.path;
import annotationprocessing.MyAnnotation;
public class TestClass {
public static class OtherNested {
static int staticInt;
}
@MyAnnotation
int staticInt;
public static void main(String[] args) {
System.out.println("other: " + TestClass.OtherNested.staticInt);
//System.out.println("not working: " + TestClass.Nested.staticInt);
System.out.println("generated: "+TestClass$Nested.staticInt);
}
}
MyAnnotationProcessor 处理源文件并生成TestClass$Nested.class 文件,但它只能通过使用TestClass$Nested 名称而不是像嵌套类中的TestClass.Nested 来访问。此外,我不能在生成代码中使用static 关键字(因为它被完全视为最高级别的类)。
也许有办法通过添加静态嵌套类来完全重写输入源代码?
【问题讨论】:
-
我知道这很旧,但如果您使用以下修复程序,您可以编写一个静态嵌套类:
filerUtils.createSourceFile(elementUtils.getBinaryName(enclosingClass) + "$Nested")
标签: java annotations annotation-processing