java - ¿Puedo obtener el nombre de una clase como una constante de tiempo de compilación sin codificarla en un literal de cadena?
reflection constants (2)
Estoy trabajando en un procesador de anotaciones. Este código compila:
package sand;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.TypeElement;
@SupportedAnnotationTypes("sand.Foo")
public class FooProcessor extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
return false; // TODO
}
}
Sin embargo, no estoy satisfecho con la cadena constante "sand.Foo" (no demasiado en este caso, pero más en general para el futuro).
Si se cambia el nombre de Foo
o se mueve a otro paquete, este código se compilará, pero no funcionará.
Me gustaría hacer algo como:
@SupportedAnnotationTypes(Foo.class)
De esa forma, si el nombre de Foo cambia, la compilación fallará y alguien tendrá que corregir el archivo.
Pero esto no funciona porque una Class
no es una String
. Así que lo intenté:
@SupportedAnnotationTypes(Foo.class.getName())
Pero el compilador no considera esto una expresión constante, que se requiere en este contexto, por lo que tampoco funcionará.
¿Hay alguna forma de forzar un literal de clase en su nombre en tiempo de compilación?
En lugar de usar la anotación, su procesador puede implementar getSupportedAnnotationTypes()
.
De esta forma, puede obtener el nombre en tiempo de ejecución del procesador.
Set<String> getSupportedAnnotationTypes() {
Set<String> supportedAnnotationTypes = new HashSet<>();
supportedAnnotationTypes.add(Foo.class.getName());
return supportedAnnotationTypes;
}
En caso de que quiera seguir utilizando anotaciones (no estándar) para esto, puede crear su propia anotación que tome un tipo de tiempo de compilación como argumento, como se sugiere @k_g. @SupportedAnnotationTypes no es nada especial, solo se usa automáticamente cuando se extiende AbstractProcessor
todos modos. La firma debería parecer así:
@Target(TYPE)
@Retention(RUNTIME)
public @interface SupportedAnnotationTypes {
Class<?>[] value();
}
Para que funcione su propia anotación, eche un vistazo al código fuente de AbstractProcessor.getSupportedAnnotationTypes()
. Básicamente llama a lo siguiente para obtener el valor de la anotación.
SupportedAnnotationTypes sat = this.getClass().getAnnotation(SupportedAnnotationTypes.class);
Puede anular getSupportedAnnotationTypes
para buscar su anotación personalizada de la misma manera.
Puedes definir el tuyo
public @interface SupportedAnnotationTypes_Class {
Class supported();
}
y luego use @SupportedAnnotationTypes_Class(supported = sand.Foo.class)
para usarlo.