Java 如何使用反射获取注释类名、属性值

Java 如何使用反射获取注释类名、属性值,java,reflection,annotations,Java,Reflection,Annotations,我知道如果我们知道注释类,我们可以很容易地获得特定的注释并访问其属性。例如: field.getAnnotation(Class<T> annotationClass) 此方法将仅返回注释接口的动态代理。与预期相反,注释的元素不是属性-它们实际上是返回提供的值或默认值的方法 您必须迭代注释的方法并调用它们来获取值。使用annotationType()获取注释的类,由getClass()返回的对象只是一个代理 下面是一个打印类注释的所有元素及其值的示例: @Resource(nam

我知道如果我们知道注释类,我们可以很容易地获得特定的注释并访问其属性。例如:

field.getAnnotation(Class<T> annotationClass) 

此方法将仅返回注释接口的动态代理。

与预期相反,注释的元素不是属性-它们实际上是返回提供的值或默认值的方法

您必须迭代注释的方法并调用它们来获取值。使用
annotationType()
获取注释的类,由
getClass()
返回的对象只是一个代理

下面是一个打印类注释的所有元素及其值的示例:

@Resource(name = "foo", description = "bar")
public class Test {

    public static void main(String[] args) throws Exception {

        for (Annotation annotation : Test.class.getAnnotations()) {
            Class<? extends Annotation> type = annotation.annotationType();
            System.out.println("Values of " + type.getName());

            for (Method method : type.getDeclaredMethods()) {
                Object value = method.invoke(annotation, (Object[])null);
                System.out.println(" " + method.getName() + ": " + value);
            }
        }

    }
}

感谢您指出,您需要使用
null
参数来避免警告。

只是为了跟进上面的答案(我没有足够的代表来回答):

应更改为以下内容,否则将引发异常:

method.invoke(annotation, (Object[])null) or method.invoke(annotation, new Object[0])

field.getAnnotations()有什么问题?通过对每个批注对象调用“annotationType()”可以轻松确定批注类。谢谢。它起作用了。注释接口没有遵循JavaBean命名约定,所以当我尝试getXXX时,我没有找到这个方法。对于属性。它也没有遵循JavaBean命名约定,我必须使用特殊的逻辑来反射地查找属性。我使用反射实现了它。这是一篇旧文章,但如果您想访问注释属性的值,可以使用以下代码:
Field[]fields=Test.class.getDeclaredFields();对于(Field-Field:fields){if(Field.isAnnotationPresent(FieldDescr.class)){MyAnnotation MyAnnotation=Field.getAnnotation(MyAnnotation.class);System.out.println(MyAnnotation.name());}}}
在上面的示例中,名称是作为注释接口的MyAnnotion的属性。谢谢,我已经用你的改进更新了我的答案!我认为它只会创建一个编译器警告,而不是一个异常,但您是对的,它应该按照您的建议进行更改。是否可以在编译时使用反射?@MohamedAouledIssa您的意思是在编译期间读取注释的值,例如验证它?常规Java反射无法做到这一点。但这可以通过编译期间运行的注释处理器来完成。与此相关的Java API是javax.annotation.processing和javax.lang.model,它们可以被描述为编译时反射,对吧!在我的职业生涯中,我写过十几个注释处理器,所以这是显而易见的,这就是它的设计目的。我的用例非常具体。我有一个android应用程序,它有多个模块,我希望能够在一个特定的模块中编写一些代码,这在注释处理器中是不可能的,即使我专门定义了输出目录。有什么办法解决这个问题吗?许多的thanks@MohamedAouledIssa注释处理器通常支持在编译期间生成附加代码。至少对于普通Java,我不知道Android注释处理在这里是否有一些限制。注释处理器不允许修改代码,但如果您需要,它显然仍然可以做到:(至少在Java中,通过修改字节码。Android在这里的工作方式可能不同,但由于Android有Lombok,我想这是可能的)安卓AP与Java AP相同。老实说,没有什么特别的,但问题是我不能让我的注释处理器在与默认处理器不同的位置生成类。如果输出目录在同一个子模块中,但决不在不同的模块中,我可以这样做。模块A中的注释处理器将无法在子模块B中生成代码。我不需要修改代码。我只需要把它输出到其他地方。
method.invoke(annotation, null)
method.invoke(annotation, (Object[])null) or method.invoke(annotation, new Object[0])