我可以将类的名称作为编译时常量获取而不用字符串文字对其进行硬编码吗? [英] Can I get a class's name as a compile-time constant without hardcoding it in a string literal?

查看:110
本文介绍了我可以将类的名称作为编译时常量获取而不用字符串文字对其进行硬编码吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究注释处理器。此代码编译:

I am working on an annotation processor. This code compiles:

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(在这种情况下不是太多,但将来会更多)。

However, I am displeased by the string constant "sand.Foo" (not too much in this case, but more in general for the future).

如果 Foo 被重命名或移动到另一个包,这段代码仍然会编译,但它不起作用。

If Foo is renamed or moved to another package, this code will still compile, but it won't work.

我想做类似的事情:

@SupportedAnnotationTypes(Foo.class)

这样,如果Foo的名称发生变化,编译将失败,有人必须更正文件。

That way, if Foo's name changes, the compilation will fail and someone will have to correct the file.

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

But this does not work because a Class is not a String. So I tried:

@SupportedAnnotationTypes(Foo.class.getName())

但编译器并不认为这是一个常量表达式,在此上下文中是必需的,因此也不会有效。

But the compiler does not consider this a constant expression, which is required in this context, so that won't work either.

在编译时是否有任何方法可以将类文字强制转换为其名称?

Is there any way to coerce a class literal into its name at compile time?

推荐答案

您的处理器可以实现 getSupportedAnnotationTypes() 在运行时提供支持的注释类型名称:

Instead of using the annotation, your processor can implement getSupportedAnnotationTypes() to provide supported annotation type names at runtime:

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


如果您想继续使用(非标准)注释,您可以创建自己的注释,将编译时类型作为参数,如@k_g建议。 @SupportedAnnotationTypes 并不是真的任何特殊的东西,它只会在你扩展 AbstractProcessor 时自动使用。看一下源代码 AbstractProcessor.getSupportedAnnotationTypes()

In case you'd like to keep using (non-standard) annotations for this, you could create your own annotation that takes a compile time type as argument, like @k_g suggested. @SupportedAnnotationTypes isn't really anything special, it is only used automatically when you are extending AbstractProcessor anyway. Take a look at the source code of AbstractProcessor.getSupportedAnnotationTypes().

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

The signature of your custom annotation should use Class<?>[] instead of String[]:

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

覆盖 getSupportedAnnotationTypes 和以与 AbstractProcessor 相同的方式查找自定义注释。例如:

Override getSupportedAnnotationTypes and look up your custom annotation in the same way as AbstractProcessor. For example like this:

public Set<String> getSupportedAnnotationTypes() {
    Class<?>[] types = getClass().getAnnotation(SupportedAnnotationTypes.class).value();
    return Arrays.stream(types).map(Class::getName).collect(Collectors.toSet());
}

这篇关于我可以将类的名称作为编译时常量获取而不用字符串文字对其进行硬编码吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆