java - 防止将 Java 注释添加到最终字段

标签 java annotations

@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/

相关文章:

java - 方面未从计划中捕获方法

android - Kotlin 注释 : Get interface inner annotated properties

java - 有条件地将数据发送到 Spring Batch 中的多个写入器

java - 优先队列问题

java - 实例变量如何在 Google App Engine 上工作? [Java]

java - 为什么我的媒体播放器不幸停止?

java - spring jpa中如何管理数据库连接池?

java - 我可以根据带注释的@WebService 类/接口(interface)自动发现 jaxws :endpoints for beans. xml 吗?

java - 使用自定义注释实现依赖注入(inject)

scala - 为什么scala人不喜欢注释?