直接用field.getannotation遍历私有字段需先调用getdeclaredfields()获取所有声明字段,再对每个field调用setaccessible(true)放开访问限制,最后用getannotation获取注解值;否则可能返回null。

直接用 Field.getAnnotation 遍历私有字段并提取注解值,关键在于:获取所有声明字段(包括 private)、设置可访问、再调用 getAnnotation。Java 反射默认不访问 private 成员,必须显式调用 setAccessible(true)。
获取所有声明字段(含 private)
使用 Class.getDeclaredFields(),它返回当前类**显式定义**的所有字段(public/private/protected),不包含父类字段。若需继承的字段,需递归处理父类。
-
getDeclaredFields()返回数组,包含 private 字段;getFields()只返回 public 字段(含父类),不能用于 private - 每个
Field对象代表一个字段,后续通过它读取注解或值
对每个字段设为可访问并获取注解
private 字段默认不可反射访问,必须调用 setAccessible(true),否则 getAnnotation 虽不报错但可能返回 null(尤其在 JDK 12+ 安全限制增强后)。
- 建议在 try-catch 中调用
setAccessible(true),捕获SecurityException - 调用
field.getAnnotation(YourAnnotation.class)获取指定类型注解实例 - 若注解不存在,返回
null,需判空再取值
完整示例代码(提取 @Column 注解的 name 属性)
假设 POJO 类如下:
@Data
public class User {
@Column(name = "user_id")
private Long id;
@Column(name = "user_name")
private String name;
private String email; // 无注解
}
遍历提取逻辑:
Class<user> clazz = User.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true); // 关键:放开访问限制
Column columnAnn = field.getAnnotation(Column.class);
if (columnAnn != null) {
System.out.println(field.getName() + " → " + columnAnn.name());
// 输出:id → user_id,name → user_name
}
}</user>
注意事项与常见坑
-
泛型字段无法直接获取注解值:如
private List<string> tags;</string>,注解在字段上,不是在泛型类型上,getAnnotation仍可用,但不要混淆类型擦除问题 -
重复注解需用 getAnnotationsByType:若用了
@Repeatable,用field.getAnnotationsByType(YourAnn.class)获取全部实例 -
模块化系统(JDK 9+)需开放模块:若运行在模块路径下,需在
module-info.java中添加opens your.package to java.base; - 避免多次 setAccessible(true):虽幂等,但频繁调用影响性能;可统一处理或封装工具方法










