文章目录
- 497. Java 反射 - 使用反射读取注解
- 1. 为什么要关心注解?
- 2. 获取注解的工具类:`AnnotatedElement`
- 3. 示例:类级别注解
- 4. 示例:重复注解 (Repeatable Annotations)
- 方式一:通过容器注解 `@Validators`
- 方式二:直接用 `getAnnotationsByType()`
- 5. 总结
497. Java 反射 - 使用反射读取注解
1. 为什么要关心注解?
在现代 Java 开发中,注解已经成为框架和库的“开关”。
- ORM 框架(如 Hibernate、JPA):用注解标记实体字段和表的映射。
- Spring:用注解实现依赖注入、事务管理、安全控制。
- 验证框架:用注解标记参数是否允许
null、是否必须符合某种格式。
👉 注解之所以能发挥作用,核心原因就是:运行时通过反射 API 读取注解并执行相应逻辑。
2. 获取注解的工具类:AnnotatedElement
以下几个反射类都实现了AnnotatedElement接口:
Class(类、接口、枚举、记录、数组)Field(字段)Method(方法)Constructor(构造函数)
它们提供了几组关键方法:
isAnnotationPresent(Class<?>):是否存在某个注解。getAnnotations():获取该元素上的所有注解(包括继承的)。getDeclaredAnnotations():只获取该元素本身声明的注解。getAnnotation(Class<?>):获取指定类型的注解实例。getAnnotationsByType(Class<?>):获取重复注解。
3. 示例:类级别注解
定义枚举和注解:
enumSerializedFormat{BINARY,XML,JSON}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interfaceBean{}@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@interfaceSerialized{SerializedFormatformat()defaultSerializedFormat.JSON;}在类上使用:
@Serialized@BeanpublicclassPerson{}通过反射读取:
Class<?>c=Person.class;booleanisBean=c.isAnnotationPresent(Bean.class);System.out.println("isBean = "+isBean);Annotation[]annotations=c.getAnnotations();for(Annotationannotation:annotations){System.out.println("annotation = "+annotation);}输出:
isBean=trueannotation=@org.devjava.Serialized(format=JSON)annotation=@org.devjava.Bean()👉 注意:返回的其实是注解类的实例对象,你可以直接调用它的方法。
Serializedserialized=c.getAnnotation(Serialized.class);System.out.println("format = "+serialized.format());输出:
format=JSON4. 示例:重复注解 (Repeatable Annotations)
定义验证规则:
enumValidationRules{NON_NULL,NON_EMPTY,NON_ZERO}@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interfaceValidators{Validator[]value();}@Target(ElementType.FIELD)@Repeatable(Validators.class)@interfaceValidator{ValidationRulesvalue();}应用在Person类的字段上:
publicclassPerson{@Validator(ValidationRules.NON_NULL)@Validator(ValidationRules.NON_EMPTY)privateStringname;}读取注解:
方式一:通过容器注解@Validators
FieldnameField=Person.class.getDeclaredField("name");Annotation[]annotations=nameField.getAnnotations();Validatorsvalidators=(Validators)annotations[0];for(Validatorv:validators.value()){System.out.println("validator = "+v);}输出:
validator=@org.devjava.Validator(NON_NULL)validator=@org.devjava.Validator(NON_EMPTY)方式二:直接用getAnnotationsByType()
Validator[]validators=nameField.getAnnotationsByType(Validator.class);for(Validatorv:validators){System.out.println("annotation = "+v);}输出:
annotation=@org.devjava.Validator(NON_NULL)annotation=@org.devjava.Validator(NON_EMPTY)👉 第二种方式更简洁,JDK 会自动帮你展开容器注解。
5. 总结
- 注解是框架的“说明书”,框架通过反射读取注解来决定如何运行。
- 类、方法、字段、构造函数都可以携带注解,并通过
AnnotatedElement访问。 isAnnotationPresent():检查是否存在。getAnnotation():获取单个注解。getAnnotationsByType():用于重复注解。