有没有办法将 Java 注释作为参数传递?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3282239/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to pass a Java annotation as a parameter?
提问by Marcos Roriz Junior
Guys is there a way to pass a Annotation as a direct parameter (rather by doing all the reflection overhead)? 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)?
伙计们有没有办法将 Annotation 作为直接参数传递(而不是通过执行所有反射开销)?例如在下面的代码中,我有一个保存 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);
}
采纳答案by Joachim Sauer
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));
}
}
回答by Andrzej Doyle
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类型参数的方法- 但是您仍然需要通过类/方法对象的反射来获取这些实例。
回答by Andrei Fierbinteanu
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.
虽然你为什么要这样做超出了我的理解。如果您需要将值传递给某个东西,您应该真正使用一个类。
回答by irreputable
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,涌出!)获得的其他信息我们可以过度架构这个东西,或者我们可以简单地创建一个运行时注释类型的对象。
回答by Oleksandr.Bezhan
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));
}