web-dev-qa-db-ja.com

Javaアノテーションをパラメーターとして渡す方法はありますか?

みんな、直接パラメータとしてアノテーションを渡す方法はありますか(すべてのリフレクションオーバーヘッドを実行するのではなく)?たとえば、次のコードでは、int値を保持するアノテーションNumberがあり、addImplメソッドにパラメーターとして渡したいのですが、どうすれば(リフレクション以外で)それを行うことができますか?

コードスニペット:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
public @interface Number {
    int value();
}

public void add(int x2) {
    addImpl(@Number(value = 10) lol, x2);
}

public void addImpl(Number a, int b) {
    System.out.println(a.value() + b);
}

public static void main(String[] args) {
    new TestClass().add(3);
}
26

はい、このような注釈を渡すことができます(通常のインターフェースであるかのように)。

実行できない唯一のことは、実行時にそのインターフェイスのインスタンスを作成することです。既存のアノテーションを取得して渡すことしかできません。

import Java.lang.annotation.*;

public class Example {

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public static @interface Number {
        int value();
    }

    @Number(value = 42)
    public int adder(final int b) throws SecurityException, NoSuchMethodException {
        Number number = getClass().getMethod("adder", int.class).getAnnotation(Number.class);
        return addImpl(number, b);
    }

    public int addImpl(final Number a, final int b) {
        return a.value() + b;
    }

    public static void main(final String[] args) throws SecurityException, NoSuchMethodException {
        System.out.println(new Example().adder(0));
    }
}
21
Joachim Sauer

あなたはそれを次のように行うことができます:

public void add(int x2) {
    addImpl(new Number() {

        @Override
        public int value() {
            return 10;
        }

        @Override
        public Class<? extends Annotation> annotationType() {
            return Number.class;
        }
    }, x2);
}

Numberは基本的にインターフェイスであるため、そのインターフェイスを実装する匿名クラスのインスタンスを作成し、それをメソッドに渡す必要があります。

あなたがこれをしたい理由は私を超えていますが。何かに値を渡す必要がある場合は、実際にはクラスを使用する必要があります。

9

私の知る限り、add実装で使用したいような、「注釈リテラル」のようなものはありません。

これに最も近いのは、タイプ Java.lang.annotation.Annotation -のパラメーターを受け取るメソッドを宣言することだと思いますが、それでもクラスからのリフレクションを介してこれらのインスタンスを取得する必要があります/ methodオブジェクト。

4
Andrzej Doyle

テストでアノテーションに合格する必要がある場合は、それをモックにすることができます。たとえば、JSR303バリデータのテストは次のようになります。

public void test() {
    final TextLengthValidator validator = new TextLengthValidator();
    validator.initialize(mock(TextLength.class));
    final boolean valid = validator.isValid("some text", mock(ConstraintValidatorContext.class));
    assertThat(valid, is(true));
}
2

Numberも古き良きインターフェースであり、具象クラスを実装できます。

みんな、これは便利です。モジュールは主にコンパイル時に修正されるアノテーションを処理しますが、実行時に他のソースから取得した他の情報(xml、gush!など)をフィードする必要がある場合もあります。注釈タイプのオブジェクト。

2
irreputable