我正在研究注释处理器。此代码编译:
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
}
}
但是,我对字符串常量“sand.Foo”感到不满(在这种情况下不是太多,但对于将来会更多)。
如果重命名Foo
或将其移动到另一个包,则此代码仍会编译,但不起作用。
我想做点什么:
@SupportedAnnotationTypes(Foo.class)
这样,如果Foo的名称发生变化,编译将失败,有人必须更正该文件。
但这不起作用,因为Class
不是String
。所以我试过了:
@SupportedAnnotationTypes(Foo.class.getName())
但编译器并不认为这是一个常量表达式,这在此上下文中是必需的,因此也不会起作用。
有没有办法在编译时将类文字强制转换为它的名字?
答案 0 :(得分:6)
您的处理器可以实现getSupportedAnnotationTypes()
以在运行时提供支持的注释类型名称,而不是使用注释:
Set<String> getSupportedAnnotationTypes() {
Set<String> supportedAnnotationTypes = new HashSet<>();
supportedAnnotationTypes.add(Foo.class.getName());
return supportedAnnotationTypes;
}
如果您希望继续使用(非标准)注释,您可以创建自己的注释,将编译时类型作为参数,如@k_g建议。 @SupportedAnnotationTypes并不是什么特别的事情,它只会在您展开AbstractProcessor
时自动使用。看看source code of AbstractProcessor.getSupportedAnnotationTypes()
。
自定义注释的签名应使用Class<?>[]
而不是String[]
:
@Target(TYPE)
@Retention(RUNTIME)
public @interface SupportedAnnotationTypes {
Class<?>[] value();
}
覆盖getSupportedAnnotationTypes
并以与AbstractProcessor
相同的方式查找自定义注释。例如:
public Set<String> getSupportedAnnotationTypes() {
Class<?>[] types = getClass().getAnnotation(SupportedAnnotationTypes.class).value();
return Arrays.stream(types).map(Class::getName).collect(Collectors.toSet());
}
答案 1 :(得分:5)
您可以定义自己的。
public @interface SupportedAnnotationTypes_Class {
Class supported();
}
然后使用@SupportedAnnotationTypes_Class(supported = sand.Foo.class)
来使用它。