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 の名前が変更された場合、コンパイルが失敗し、誰かがファイルを修正する必要があります。

しかし、 a は aClassではないため、これは機能しません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が提案したように、コンパイル時の型を引数として取る独自の注釈を作成できます。@SupportedAnnotationTypesAbstractProcessorは特別なものではなく、とにかく拡張するときにのみ自動的に使用されます。のソースコードをAbstractProcessor.getSupportedAnnotationTypes()見てみましょう。

カスタム アノテーションの署名は、Class<?>[]代わりにString[]次のものを使用する必要があります。

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

getSupportedAnnotationTypesと同じ方法で、カスタム アノテーションをオーバーライドしてルックアップしますAbstractProcessor。たとえば、次のようにします。

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 に答える