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