@MyAnnotation
final Integer value;
¿Es posible configurar un MyAnnotation anotación personalizada de una manera que hará que un error de tiempo de compilación anterior, pero no hay error en tiempo de compilación cuando se añade a un campo no final? (Independientemente de su nivel de acceso).
información de fondo: en nuestro código, tenemos una anotación especial que disparadores Modificación de a través de la reflexión de una clase fuera y esto no se puede hacer para los campos finales, por lo que nos gustaría advertir a los usuarios de la anotación en tiempo de compilación (en la actualidad tenemos un tiempo de ejecución comprobar que lanzar una excepción).
Una opción es un procesador de anotación . Por ejemplo, si usted tiene la siguiente anotación:
package com.example;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME) // must be at least SOURCE
@Target(ElementType.FIELD)
public @interface Foo {}
Entonces el siguiente emitirá un error si @Foo
está presente en un final
campo:
package com.example;
import javax.annotation.processing.AbstractProcessor;
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.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
import java.util.Set;
@SupportedAnnotationTypes("com.example.Foo")
@SupportedSourceVersion(SourceVersion.RELEASE_13) // or whatever version you support
public class FooProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
if (!annotations.isEmpty()) {
// This processor is only declared to process one annotation
TypeElement foo = annotations.iterator().next();
for (Element element : roundEnv.getElementsAnnotatedWith(foo)) {
for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
if (mirror.getAnnotationType().asElement().equals(foo)
&& element.getModifiers().contains(Modifier.FINAL)) {
// processingEnv is a protected field of AbstractProcessor
processingEnv.getMessager()
.printMessage(Kind.ERROR, "Field cannot be final.", element, mirror);
break;
}
}
}
}
return true;
}
}
En el código anterior sólo se utiliza la API de modelo (por ejemplo TypeElement
) para hacer referencia a la Foo
anotación. Nótese, sin embargo, que la API procesador de anotación sí permite que se debe usar la clase de la anotación (por ejemplo Foo.class
) si la anotación es visible (es decir, el procesador tiene una dependencia en la anotación). Utilizando el API de la clase puede ser más fácil de usar, fácil de razonar sobre, y más fácil de leer a utilizarlo si su clase de anotación es visible a su clase de procesador.
A continuación, tendría que decirle javac
a utilizar el procesador de anotación. Ver la especificación de herramientas para obtener más información; Específicamente, mira los --processor-path
, --processor-module-path
, -processor
, y -proc
opciones estándar, así como la sección de procesamiento de anotación.
Nota Es posible que no sea capaz de imponer el uso de su procesador de anotación.