@MyAnnotation
final Integer value;
是否可以配置自定义注解 MyAnnotation 导致上述编译时错误,但添加到非 final 字段时不会出现编译时错误? (无论访问级别如何)。
背景信息:在我们的代码中,我们有一个特殊的注释,可以通过外部类的反射触发修改,这不能用于最终字段,所以我们想在编译时警告用户注释(目前我们有一个会抛出异常的运行时检查)。
最佳答案
一个选项是 annotation processor .例如,如果您有以下注释:
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 {}
如果 @Foo
出现在 final
字段中,则以下代码将发出错误:
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;
}
}
在上面的代码中,我只使用了模型 API(例如 TypeElement
)来引用 Foo
注释。但是请注意,如果注释可见(即您的处理器依赖于注释),则注释处理器 API 确实允许使用注释的类(例如 Foo.class
)。使用类 API 可以更易于使用、更易于推理和更易于阅读 - 如果您的注释类对您的处理器类可见,请使用它。
然后您需要告诉 javac
使用注释处理器。查看tool specification了解更多信息;具体来说,查看 --processor-path
、--processor-module-path
、-processor
和 -proc
标准选项以及 the section关于注释处理。
请注意,您可能无法强制使用注释处理器。
关于java - 防止将 Java 注释添加到最终字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58629837/