我正在研究注释处理器。此代码编译:
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())
但是编译器不认为这是一个常量表达式,而在这种情况下这是必需的,所以这也不起作用。
有什么方法可以在编译时将类文字强制转换为它的名称吗?
最佳答案
您的处理器可以实现 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());
}
关于java - 我可以在不将类名硬编码为字符串文字的情况下将类名作为编译时常量获取吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27955169/