4

あなたはJavaの魔法使いだと思いますか?

あなたはリフレクション 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 を記述して、メソッド Cx() および Mark.class で呼び出された場合に {c, d} を返すようにする必要があります。

(これは宿題ではなく、私が開発しようとしているフレームワーク メタプログラミング フレームワークの実際のプログラミング課題です)

4

2 に答える 2

6

これは動作することがテストされています。必要以上に大変でした。

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

私は、なぜannotationType()が機能するのかという疑問を投げかけるだけだと思いますが、getClass()は機能しません。

于 2009-08-31T21:44:05.680 に答える
1

実際、これがどれほどトリッキーなのか、私にはわかりません。

更新、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

これには、すべての注釈が実行時レベルの保持でマークされている必要があることに注意してください。おそらく、実際の型 (私の例では A.class) でいっぱいの Class[] を返したいと思うでしょう。

于 2009-08-31T21:27:25.510 に答える