17

我正在开发注释处理器。此代码编译:

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 的名称更改,编译将失败,并且必须有人更正文件。

但这不起作用,因为 aClass不是 a String。所以我尝试了:

@SupportedAnnotationTypes(Foo.class.getName())

但是编译器不认为这是一个常量表达式,在这种情况下这是必需的,所以它也不起作用。

有没有办法在编译时将类文字强制转换为其名称?

4

2 回答 2

6

getSupportedAnnotationTypes()您的处理器可以实现在运行时提供支持的注解类型名称,而不是使用注解:

Set<String> getSupportedAnnotationTypes() {
    Set<String> supportedAnnotationTypes = new HashSet<>();
    supportedAnnotationTypes.add(Foo.class.getName());
    return supportedAnnotationTypes;
} 



如果您想为此继续使用(非标准)注释,您可以创建自己的注释,该注释将编译时类型作为参数,如@k_g 建议的那样。@SupportedAnnotationTypes并没有什么特别之处,它只会在您进行扩展时自动使用AbstractProcessor。看一下源代码AbstractProcessor.getSupportedAnnotationTypes()

您的自定义注释的签名应该使用Class<?>[]而不是String[]

@Target(TYPE)
@Retention(RUNTIME)
public @interface SupportedAnnotationTypes {
    Class<?>[] value();
}

getSupportedAnnotationTypesAbstractProcessor. 例如像这样:

public Set<String> getSupportedAnnotationTypes() {
    Class<?>[] types = getClass().getAnnotation(SupportedAnnotationTypes.class).value();
    return Arrays.stream(types).map(Class::getName).collect(Collectors.toSet());
}
于 2015-01-15T01:02:51.023 回答
5

你可以定义你自己的。

public @interface SupportedAnnotationTypes_Class {
    Class supported();
}

然后@SupportedAnnotationTypes_Class(supported = sand.Foo.class)使用它。

于 2015-01-15T01:07:43.737 回答