有没有办法将Java注释作为参数传递?

时间:2010-07-19 15:00:51

标签: java annotations

Guys有办法将Annotation作为直接参数传递(而不是通过执行所有反射开销)吗?例如,在下面的代码中,我有一个包含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);
}

5 个答案:

答案 0 :(得分:21)

是的,您可以传递这样的注释(就像它们是普通的接口一样)。

您唯一不能做的是在运行时创建该接口的实例。您只能使用现有注释并传递它们。

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));
    }
}

答案 1 :(得分:9)

你可以这样做:

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基本上是一个接口,因此您必须创建一个实现该接口的匿名类的实例,并将其传递给该方法。

虽然你想要这样做的原因超出了我的范围。如果你需要将值传递给某个东西,你应该真正使用一个类。

答案 2 :(得分:4)

据我所知,没有“注释文字”这样的东西,因为你想在add实现中使用它。

我认为最接近于此的方法是声明方法采用类型java.lang.annotation.Annotation的参数 - 但是你仍然需要通过类/方法对象的反射来获取这些实例。

答案 3 :(得分:2)

Number也是一个很好的旧界面,你可以实现一个具体的类。

伙计们,这很有用。虽然模块主要处理在编译时修复的注释,但有时我们需要在运行时从其他源(例如xml,gush!)获取其他信息。我们可以过度构建事物,或者我们可以简单地创建运行时注释类型的对象。

答案 4 :(得分:2)

如果你需要在测试中传递注释,你可以模拟它。 例如,JSR 303验证器的测试可能如下所示:

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));
}