给定类型的动态变量

时间:2010-08-09 13:51:53

标签: java reflection

我写了一个小类,它从方法中读出注释 现在我想扩展该类以使其更具动态性。

我的课目前使用以下代码来读出注释:

ExtendedCommandAnnotation e = foo.getClass()
                                 .getAnnotation(ExtendedCommandAnnotation.class);
String startTag = e.annoPropStartTag();

这是固定注释的简单案例 在新版本中,我没有任何固定的注释。我将在变量中获得注释“ExtendedCommandAnnotation” 因此,上面的代码将被编辑为:

String className= "ExtendedCommandAnnotation";
??? e = foo.getClass().getAnnotation(Class.forName(className));
String startTag = e.annoPropStartTag();

我不知道我要放什么而不是???。我用Annotation尝试过,但后来我无法用定义的方法获得属性 有没有办法让这个工作?

我的注释“类”:

@Retention( RetentionPolicy.RUNTIME )
public @interface ExtendedCommandAnnotation
{
    String   annoPropUseTab() default "0";
    String   annoPropStartTag() default "";
    String   annoPropEndTag() default "";
}

编辑:

最后我得到了类似的东西:         String [] cmdMethNames = this.getAvailableCommandNames();

    Class<?> annotationClass = Class.forName(this.annotationClassName); 

    for( Method meth : cmdMeth )
    {
        HashMap<String, String> tempAnno = new HashMap<String, String>();
        if (meth.isAnnotationPresent((Class<? extends Annotation>) annotationClass))
        {
            Annotation anno = meth.getAnnotation((Class<? extends Annotation>) annotationClass);
            [...]
        }
        [...]
    }

但是对(Class<? extends Annotation>)的强制转换会发出以下警告:“类型安全:未经检查从类&lt; capture#4-of?&gt;转换为类&lt;?extends Annotation&gt; ”< / p>

2 个答案:

答案 0 :(得分:2)

如果您事先不知道注释,则无法知道它有annoPropStartTag()方法,是吗?所以你不能告诉编译器如何绑定到那个方法...

如果你想在执行时基本上找到一个具有该名称的方法,你现在需要使用反射。

您可能需要考虑使用某种“基础”注释类型,其中包含一般情况下所需的所有方法,然后从中派生所有其他注释类型。

答案 1 :(得分:1)

/* Foo.java */

@ExtendedCommandAnnotation(annoPropStartTag = "hello")
public class Foo {
}



/* ExtendedCommandAnnotation.java */

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention( RetentionPolicy.RUNTIME )
public @interface ExtendedCommandAnnotation {
    String annoPropUseTab() default "0";
    String annoPropStartTag() default "";
    String annoPropEndTag() default "";
}



/* Main.java */

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class Main {
    public static void main(String[] args) {
        doOriginalImplementation();     // Prints "hello"
        doReflectionImplementation();   // Prints "hello"
    }

    public static void doOriginalImplementation() {
        Foo foo = new Foo();
        ExtendedCommandAnnotation e = foo.getClass().getAnnotation(ExtendedCommandAnnotation.class);
        String startTag = e.annoPropStartTag();
        System.out.println(startTag);
    }

    public static void doReflectionImplementation() {
        Foo foo = new Foo();

        Annotation[] annotations = foo.getClass().getAnnotations();
        // or the statement below, depends on what you intent to do:
        // Annotation[] annotations = foo.getClass().getDeclaredAnnotations();

        Class classOfExtendedCommandAnnotation = null;
        Annotation annotationOnClassFoo = null;
        for (Annotation a : annotations) {
            Class classA = a.annotationType();
            if ("ExtendedCommandAnnotation".equals(classA.getName())) {
                classOfExtendedCommandAnnotation = classA;
                annotationOnClassFoo = a;
                break;
            }
        }

        Method methodAnnoPropStartTag = null;
        if (classOfExtendedCommandAnnotation != null) {
            try {
                methodAnnoPropStartTag = classOfExtendedCommandAnnotation.getMethod("annoPropStartTag");
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }

        if (methodAnnoPropStartTag != null) {
            try {
                String startTag = (String) methodAnnoPropStartTag.invoke(annotationOnClassFoo);
                System.out.println(startTag);
            } catch (ClassCastException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (IllegalArgumentException e) {
                throw new RuntimeException(e);
            } catch (InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

在我的解决方案中,类ExtendedCommandAnnotation不需要在编译时出现。但是,必须存在班级Foo。可以稍微修改一下解决方案,以便类Foo也不需要出现。