Ich versuche, den Wert einer Enumeration in einer Annotation mithilfe eines Annotation Processor und Annotation Mirror zu lesen, aber ich bekomme null zurück. Ich denke, das hat mit dem AnnotationValue zu tun, das eine Enum als VariableElement umschließt. Das doc für VariableElement # getConstantValue() sagt "Gibt den Wert dieser Variablen zurück, wenn es sich um ein letztes Feld handelt, das mit einer Kompilierzeitkonstante initialisiert wird." Okay, aber final ist kein gültiger Modifikator für ein Anmerkungselement. Außerdem habe ich keine Probleme andere Annotationswerte zu lesen, nur Enums.So erfassen Sie eine Enum aus einem AnnotationValue in einem Annotation Processor
Ich habe einige Nachforschungen gemacht und es scheint, dass der AnnotationValue zur Laufzeit als Symbol.VarSymbol instanziiert wird, aber Symbol.VarSymbol # getConstantValue() sieht so aus, als sollte es nur das Objekt zurückgeben.
Schließlich, wenn ich eine toString() auf den AnnotationValue mache, bekomme ich den richtigen Wert.
Die Annotation:
package annotation;
public @interface AnAnnotation
{
String value();
Behavior defaultBehavior() default Behavior.NEW;
public static enum Behavior
{
NEW, NULL;
}
}
Teil meines Prozessors und in einer Vielzahl von verschachtelten Schleifen an der richtigen AnnotaionMirror zu bekommen:
Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValues = elemUtils.getElementValuesWithDefaults(annotationMirror);
for (ExecutableElement method : annotationValues.keySet())
{
...
else if ("defaultBehavior".equals(method.getSimpleName().toString()))
{
defaultBehavior = (Behavior)((VariableElement)annotationValues.get(method).getValue()).getConstantValue();
// This prints "NEW" or "NULL" correctly
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,annotationValues.get(method).toString());
// This prints null incorrectly (expect "NEW" or "NULL")
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, defaultBehavior + "");
}
...
}
EDIT: eine vollständigere Version des Prozessors.
package annotation.processor;
import java.util.*;
import javax.annotation.processing.*;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
import javax.lang.model.util.*;
import javax.tools.*;
import annotation.AnAnnotation;
import annotation.AnAnnotation.Behavior;
@SupportedAnnotationTypes("annotation.AnAnnotation")
public class AnAnnotationProcessor extends AbstractProcessor
{
Types typeUtils;
Elements elemUtils;
@Override
public void init(ProcessingEnvironment processingEnv)
{
super.init(processingEnv);
typeUtils = processingEnv.getTypeUtils();
elemUtils = processingEnv.getElementUtils();
}
@Override
public boolean process(Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv)
{
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
"Entering AnnotationNullableClassProcessor");
/****** Iterate over all annotaions being processed (only AnAnnotation) ******/
for (TypeElement annotation : annotations)
{
/****** Iterate over all elements that are annotated with the annotation ******/
for (Element element : roundEnv.getElementsAnnotatedWith(annotation))
{
/****** Iterate over all the declared annotations of the element ******/
for (AnnotationMirror annotationMirror : element.getAnnotationMirrors())
{
final String annotationTypeName = annotationMirror.getAnnotationType().toString();
// Process annotations of type AnAnnotation
if (annotationTypeName.equals(AnAnnotation.class.getName()))
{
Map<? extends ExecutableElement, ? extends AnnotationValue> annotationValues = elemUtils.getElementValuesWithDefaults(annotationMirror);
/****** Iterate over the annotation's values. ******/
for (ExecutableElement method : accessorValues.keySet())
{
if ("defaultBehavior".equals(method.getSimpleName().toString()))
{
Behavior defaultBehavior = (Behavior)((VariableElement)annotationValues.get(method).getValue()).getConstantValue();
// This prints "NEW" or "NULL" correctly
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,annotationValues.get(method).toString());
// This prints null incorrectly (expect "NEW" or "NULL")
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, defaultBehavior + "");
}
}
}
}
}
}
return true;
}
}
Ich habe vergessen zu erwähnen, dass dies die Java SE 6 Version der Annotationsverarbeitung ist. –