简体   繁体   English

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

[英]Is there a way to pass a Java annotation as a parameter?

Guys is there a way to pass a Annotation as a direct parameter (rather by doing all the reflection overhead)? 伙计们有一种方法可以将Annotation作为直接参数传递(而不是通过执行所有反射开销)? For example in the following code, I have a annotation Number that holds a int value, I want to pass as a parameter to the addImpl method, how can I do that (other than by reflection)? 例如,在下面的代码中,我有一个包含int值的注释Number,我想作为参数传递给addImpl方法,我该怎么做(除了通过反射)?

Code Snippet: 代码片段:

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

Yes, you can pass around annotations like this (just as if they were normal interfaces). 是的,您可以传递这样的注释(就像它们是正常的接口一样)。

The only thing you can't do is to create instances of that interface at runtime. 您不能做的唯一事情是在运行时创建该接口的实例。 You can only take existing annotations and pass them around. 您只能使用现有注释并传递它们。

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

You can do it like: 你可以这样做:

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

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

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

Since Number is basically an interface, you have to create an instance of an anonymous class that implements that interface, and pass that to the method. 由于Number基本上是一个接口,因此您必须创建一个实现该接口的匿名类的实例,并将其传递给该方法。

Although why you want to do this is beyond me. 虽然你想要这样做的原因超出了我的范围。 If you need to pass a value to something, you should really use a class. 如果你需要将值传递给某个东西,你应该真正使用一个类。

To the best of my knowledge, there's no such thing as an "annotation literal" as you want to use it in your add implementation. 据我所知,没有“注释文字”这样的东西,因为你想在你的add实现中使用它。

I think the closest thing to this would be to declare the method to take a parameter of type java.lang.annotation.Annotation - but then you'd still need to obtain those instances via reflection from the class/method objects. 我认为最接近的是声明方法采用java.lang.annotation.Annotation类型的参数 - 但是你仍然需要通过类/方法对象的反射来获取这些实例。

If you need to pass annotation in test, you can make mock of it. 如果你需要在测试中传递注释,你可以模拟它。 For example test of JSR 303 validator could look like this: 例如,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));
}

Number is also a good old interface, you can implement a concrete class. Number也是一个很好的旧接口,可以实现一个具体的类。

Guys, this is useful. 伙计们,这很有用。 While a module mostly deals with annotations which are fixed at compile time, sometimes we need to feed it other info obtained at runtime from other sources(like xml, gush!) We can over-architect the thing, or we can simply creat a runtime object of the annotaion type. 虽然模块主要处理在编译时修复的注释,但有时我们需要在运行时从其他源(例如xml,gush!)获取其他信息。我们可以过度构建事物,或者我们可以简单地创建运行时注释类型的对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM