497. Java 反射 - 使用反射读取注解

文章目录

  • [497. Java 反射 - 使用反射读取注解](#497. Java 反射 - 使用反射读取注解)
    • [1. 为什么要关心注解?](#1. 为什么要关心注解?)
    • [2. 获取注解的工具类:`AnnotatedElement`](#2. 获取注解的工具类:AnnotatedElement)
    • [3. 示例:类级别注解](#3. 示例:类级别注解)
    • [4. 示例:重复注解 (Repeatable Annotations)](#4. 示例:重复注解 (Repeatable Annotations))
      • [方式一:通过容器注解 `@Validators`](#方式一:通过容器注解 @Validators)
      • [方式二:直接用 `getAnnotationsByType()`](#方式二:直接用 getAnnotationsByType())
    • [5. 总结](#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. 示例:类级别注解

定义枚举和注解:

java 复制代码
enum SerializedFormat { BINARY, XML, JSON }

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Bean {}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Serialized {
    SerializedFormat format() default SerializedFormat.JSON;
}

在类上使用:

java 复制代码
@Serialized
@Bean
public class Person {}

通过反射读取:

java 复制代码
Class<?> c = Person.class;

boolean isBean = c.isAnnotationPresent(Bean.class);
System.out.println("isBean = " + isBean);

Annotation[] annotations = c.getAnnotations();
for (Annotation annotation : annotations) {
    System.out.println("annotation = " + annotation);
}

输出:

java 复制代码
isBean = true
annotation = @org.devjava.Serialized(format=JSON)
annotation = @org.devjava.Bean()

👉 注意:返回的其实是注解类的实例对象,你可以直接调用它的方法。

java 复制代码
Serialized serialized = c.getAnnotation(Serialized.class);
System.out.println("format = " + serialized.format());

输出:

java 复制代码
format = JSON

4. 示例:重复注解 (Repeatable Annotations)

定义验证规则:

java 复制代码
enum ValidationRules { NON_NULL, NON_EMPTY, NON_ZERO }

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Validators {
    Validator[] value();
}

@Target(ElementType.FIELD)
@Repeatable(Validators.class)
@interface Validator {
    ValidationRules value();
}

应用在 Person 类的字段上:

java 复制代码
public class Person {
    @Validator(ValidationRules.NON_NULL)
    @Validator(ValidationRules.NON_EMPTY)
    private String name;
}

读取注解:

方式一:通过容器注解 @Validators

java 复制代码
Field nameField = Person.class.getDeclaredField("name");
Annotation[] annotations = nameField.getAnnotations();
Validators validators = (Validators) annotations[0];
for (Validator v : validators.value()) {
    System.out.println("validator = " + v);
}

输出:

java 复制代码
validator = @org.devjava.Validator(NON_NULL)
validator = @org.devjava.Validator(NON_EMPTY)

方式二:直接用 getAnnotationsByType()

java 复制代码
Validator[] validators = nameField.getAnnotationsByType(Validator.class);
for (Validator v : validators) {
    System.out.println("annotation = " + v);
}

输出:

java 复制代码
annotation = @org.devjava.Validator(NON_NULL)
annotation = @org.devjava.Validator(NON_EMPTY)

👉 第二种方式更简洁,JDK 会自动帮你展开容器注解。


5. 总结

  • 注解是框架的"说明书",框架通过反射读取注解来决定如何运行。
  • 类、方法、字段、构造函数 都可以携带注解,并通过 AnnotatedElement 访问。
  • isAnnotationPresent():检查是否存在。
  • getAnnotation():获取单个注解。
  • getAnnotationsByType():用于重复注解。
相关推荐
专注仿真2 小时前
问答大模型技术方案算法实现-RAPTOR树构建算法与BEG集成使用
python·算法
eralong2 小时前
Java 面向对象:继承、多态、接口
java·后端
哦虎!2 小时前
【数据库】事务
java·数据库·mysql
CDN3602 小时前
流媒体加速实践:出海东南亚短视频点播频繁缓冲,HLS 分片与 Nginx 配置调优
java·网络·nginx·流媒体加速
冯汉栩2 小时前
Swift Control View,Label渐变颜色(源码)
开发语言·ios·swift
程序员黑豆2 小时前
Java中的null与NullPointerException完全指南:安全处理、实战排查与面试题
java·前端·ai编程
晴天163 小时前
Electron面试题-Day19
java·javascript·electron
从小就看凹凸曼^o^3 小时前
Python基础5 - 字典与集合:(1)字典
开发语言·python
GeekZHR3 小时前
C语言指针进阶补充6:动态内存管理、mem系列内存函数、复杂指针声明,一次补齐指针的“三大盲区“
java·c语言·算法·指针