我正在尝试做一些Java注释魔术。我必须说我仍在追赶注释技巧,而且某些事情对我来说仍然不太清楚。
所以...我有一些带注释的类,方法和字段。我有一个方法,它使用反射对类运行一些检查并将一些值注入到类中。一切正常。
但是,我现在面临的情况是我需要一个注释的实例(可以这么说)。所以...注释不像常规接口,你不能做一个类的匿名实现。我知道了。我在这里看了一些关于类似问题的帖子,但我似乎无法找到我正在寻找的答案。
我基本上想得到一个注释的实例,并能够使用反射设置它的一些字段(我想)。有没有办法做到这一点?
好吧,显然没有什么比这更复杂了。真!
正如同事所指出的,你可以简单地创建一个匿名的注释实例(就像任何接口一样):
MyAnnotation:
public @interface MyAnnotation
{
String foo();
}
调用代码:
class MyApp
{
MyAnnotation getInstanceOfAnnotation(final String foo)
{
MyAnnotation annotation = new MyAnnotation()
{
@Override
public String foo()
{
return foo;
}
@Override
public Class<? extends Annotation> annotationType()
{
return MyAnnotation.class;
}
};
return annotation;
}
}
积分兑换Martin Grigorov。
Gunnar's answer中建议的代理方法已在GeAnTyRef中实现:
Map<String, Object> annotationParameters = new HashMap<>();
annotationParameters.put("name", "someName");
MyAnnotation myAnnotation = TypeFactory.annotation(MyAnnotation.class, annotationParameters);
这将产生一个等同于你得到的注释:
@MyAnnotation(name = "someName")
以这种方式生成的注释实例将与通常由Java生成的注释实例相同,并且它们的hashCode
和equals
已经正确实现了兼容性,因此没有像在接受的答案中直接实例化注释那样奇怪的警告。事实上,JDK内部使用相同的方法:sun.reflect.annotation.AnnotationParser#annotationForMap。
库本身很小,没有依赖性。
披露:我是GeAnTyRef背后的开发人员。
你可以使用sun.reflect.annotation.AnnotationParser.annotationForMap(Class, Map)
:
public @interface MyAnnotation {
String foo();
}
public class MyApp {
public MyAnnotation getInstanceOfAnnotation(final String foo) {
MyAnnotation annotation = AnnotationParser.annotationForMap(
MyAnnotation.class, Collections.singletonMap("foo", "myFooResult"));
}
}
缺点:来自sun.*
的类在更高版本中可能会发生变化(尽管此方法自Java 5以来具有相同的签名)并且不适用于所有Java实现,请参阅this discussion。
如果这是一个问题:您可以使用自己的InvocationHandler
创建一个通用代理 - 这正是AnnotationParser
在内部为您做的事情。或者您使用自己的MyAnnotation
实现定义here。在这两种情况下,你应该记住实现annotationType()
,equals()
和hashCode()
,因为结果是专门针对java.lang.Annotation
记录的。