Java元编程难题:获取所有本身由给定注释a注释的注释
您认为自己是java向导吗?Java元编程难题:获取所有本身由给定注释a注释的注释,java,metaprogramming,puzzle,annotations,Java,Metaprogramming,Puzzle,Annotations,您认为自己是java向导吗? public @interface @a {} public @interface @b {} @Mark public @interface @c {} @Mark public @interface @d {} public @interface @e {} public Class C { @a @b @c @d @e public void x(); } public class Solver { public Annotatio
public @interface @a {}
public @interface @b {}
@Mark public @interface @c {}
@Mark public @interface @d {}
public @interface @e {}
public Class C
{
@a @b @c @d @e public void x();
}
public class Solver
{
public Annotation[] solve(Method m, Class c);
}
您是否精通反射API的秘密?
public @interface @a {}
public @interface @b {}
@Mark public @interface @c {}
@Mark public @interface @d {}
public @interface @e {}
public Class C
{
@a @b @c @d @e public void x();
}
public class Solver
{
public Annotation[] solve(Method m, Class c);
}
您必须编写方法solve,这样,如果在方法C.x()和Mark.class上调用它,它将返回{C,d}
(这不是家庭作业,是我试图开发的框架元编程框架的真正编程任务)事实上,我不明白这有多么棘手 更新时,忘记包含contains函数,并且将Annotation.getClass()与Annotation.annotationType()切换时出错。此代码有效
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
@Mark
public @interface A {}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface B {}
@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.TYPE)
public @interface Mark {}
public class C {
@A @B public void f() {}
}
public class Solver {
public static boolean contains(Annotation a, Class<?> targetAnnotation) {
Class<?> c = a.annotationType();
Annotation[] cas = c.getAnnotations();
for (Annotation aa : cas) {
if (aa.annotationType().equals(targetAnnotation)) {
return true;
}
}
return false;
}
public static Annotation[] getMarked(Method m) {
List<Annotation> retVal = new ArrayList<Annotation>();
for (Annotation a : m.getAnnotations()) {
if (contains(a.getClass().getAnnotations(), Mark.class) {
retVal.add(a);
}
}
return retVal.toArray(new Annotation[]{});
}
public static void main(String[] args) throws SecurityException, NoSuchMethodException {
Annotation[] result = getMarked(C.class.getMethod("f"));
}
} // solver
@Retention(RetentionPolicy.RUNTIME)
@目标({ElementType.METHOD})
@标记
公共@接口A{}
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.METHOD})
public@interface B{}
@保留(RetentionPolicy.RUNTIME)
@目标(值=ElementType.TYPE)
公共@接口标记{}
公共C类{
@A@B public void f(){}
}
公共类求解器{
公共静态布尔包含(注释a,类targetAnnotation){
类别c=a.annotationType();
注释[]cas=c.getAnnotations();
对于(注释aa:cas){
if(aa.annotationType().equals(targetAnnotation)){
返回true;
}
}
返回false;
}
公共静态注释[]已标记(方法m){
List retVal=new ArrayList();
对于(注释a:m.getAnnotations()){
if(包含(a.getClass().getAnnotations(),Mark.class){
回复。添加(a);
}
}
返回retVal.toArray(新注释[]{});
}
公共静态void main(字符串[]args)引发SecurityException、NoSuchMethodException{
注释[]结果=getMarked(C.class.getMethod(“f”);
}
}//解算器
请注意,这要求所有注释都标记为运行时级别保留,并且返回注释[]可能不是您想要的。您可能希望返回一个包含实际类型的类[](在我的示例中为a.Class)这是经过测试的。这确实比应该的更难
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface a{}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface b{}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
public @interface Mark{}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Mark
public @interface c{}
public static class D {
@a @b @c
public void x() {}
}
public static void main(String[] args) throws Exception {
Method m = D.class.getMethod("x");
Collection<Annotation> ret = new HashSet<Annotation>();
Annotation[] annotations = m.getAnnotations();
for (Annotation annotation : annotations) {
Annotation subAnnots = annotation.annotationType().getAnnotation(Mark.class);
if (subAnnots != null) {
ret.add(annotation);
}
}
System.out.println(ret);
}
@Retention(RetentionPolicy.RUNTIME)
@目标(ElementType.METHOD)
公共@接口a{}
@保留(RetentionPolicy.RUNTIME)
@目标(ElementType.METHOD)
public@interface b{}
@保留(RetentionPolicy.RUNTIME)
@目标({ElementType.TYPE,ElementType.ANNOTATION\u TYPE})
公共@接口标记{}
@保留(RetentionPolicy.RUNTIME)
@目标(ElementType.METHOD)
@标记
public@interface c{}
公共静态D类{
@a@b@c
公共void x(){}
}
公共静态void main(字符串[]args)引发异常{
方法m=D.class.getMethod(“x”);
Collection ret=new HashSet();
Annotation[]annotations=m.getAnnotations();
用于(注释:注释){
Annotation subAnnots=Annotation.annotationType().getAnnotation(Mark.class);
if(子注释!=null){
ret.add(注释);
}
}
系统输出打印项次(ret);
}
我想这就引出了一个问题:为什么annotationType()有效,而getClass()无效。你认为我会因为你暗示我(不是)而为你的作业编写代码而绊倒吗一个向导?还有,Meta就是谋杀:我是一个java向导,这对我来说太琐碎了,所以我只是用向导的方式嘲笑你。唯一令人困惑的是,为什么你认为这是一个难题。你尝试了什么?发生了什么事?默认的保留策略是什么?你在注释上指定了RetentionPolicy.RUNTIME吗?否则-它们在运行时被擦除。他是对的,我的原始代码不起作用,因为我使用的是Annotation.getClass(),我应该使用Annotation.annotationType()。在处理反射时很容易被缠绕在轴上。Annotation.getClass()将返回类,而不是它所表示的注释的类。元编程有时很难看!具体来说,注释对象是特定于要注释的单个类的代理对象。因为它是元对象,所以getClass()是注释实例的类,而annotationType()是getClass()的元等价物谢谢杰里科,这很有道理。