实现自定义变量注解需定义@Target(ElementType.FIELD)和@Retention(RetentionPolicy.RUNTIME)的注解,并通过反射调用getDeclaredFields()与getAnnotation()安全读取;属性须有合法默认值,避免null及作用域错配。

要实现自定义变量注解并在运行时解析,关键在于两点:一是正确定义作用于字段(FIELD)的 RUNTIME 级注解;二是通过反射安全获取并读取字段上的注解属性。变量注解和方法、类注解在定义逻辑上一致,但目标位置和使用场景不同——它常用于数据绑定、校验、序列化或 ORM 映射等场景。
定义变量级 RUNTIME 注解
必须用 @Target(ElementType.FIELD) 限定只能标注在成员变量上,且 @Retention(RetentionPolicy.RUNTIME) 是硬性前提,否则反射无法读到。
- 属性类型仅限:基本类型、
String、Class<?>、枚举、其他注解,或它们的一维数组(如String[]) - 每个属性必须有
default值(null不合法),否则使用时必须显式赋值 - 示例定义:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
String name() default "";
boolean nullable() default true;
String type() default "VARCHAR";
}
在字段上使用注解
直接写在类的成员变量前,支持省略 value() 名(若存在且唯一需设值),其余属性用键值对形式。
- 合法写法:
@Column(name = "user_name", nullable = false) - 若只设
name且它是唯一无默认值的属性(或只有value()),可简写为:@Column("user_name") - 数组写法:
@Column(name = "tags", type = "TEXT", nullable = false)(注意不能写default null)
运行时解析字段注解
通过 Class.getDeclaredFields() 获取所有字段,再逐个调用 field.getAnnotation(YourAnnotation.class)。务必先判空,避免 NPE。
- 推荐方式:
if (field.isAnnotationPresent(Column.class)) { Column col = field.getAnnotation(Column.class); ... } - 不建议用
toString()或equals()比较注解对象,它只是 JVM 生成的代理实例 - 注意:
getDeclaredAnnotations()返回全部注解数组,getAnnotation()才按类型精准获取 - 性能提示:频繁反射建议缓存字段+注解结果,或结合 Spring 的
ReflectionUtils工具类简化操作
常见踩坑点
很多“读不到注解”的问题其实源于配置疏漏:
- 忘了加
@Retention(RetentionPolicy.RUNTIME)—— 编译后注解就消失了 - 用了
@Target(ElementType.METHOD)却标在字段上,编译直接报错 - 属性声明为
String value() default null——null不是合法默认值,编译失败 - 反射时未调用
setAccessible(true)访问 private 字段(若字段非 public) - 误用
getAnnotations()(只返回 public 父类继承的)而非getDeclaredAnnotations()

















