@target(elementtype.field)表示自定义注解仅限用于字段,需配合@retention(retentionpolicy.runtime)才能在运行时通过反射读取并校验,如notnull注解校验字段非空。

<p>@Target(ElementType.FIELD) 表示该自定义注解只能用在类的成员变量(即字段)上,不能用在方法、类、参数等其他位置。</p>
<h3>配置方式:在自定义注解上声明 @Target</h3>
<p>你需要在定义注解时,显式加上 <strong>@Target(ElementType.FIELD)</strong>,例如:</p>
<font color="blue">
<pre class="brush:php;toolbar:false;">
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotNull {
String message() default "字段不能为空";
}
这样定义后,这个 @NotNull 注解就只能标注在字段上,比如:
public class User {
@NotNull
private String name; // ✅ 合法
@NotNull
public void setName(String name) { } // ❌ 编译报错:非法使用注解
}
为什么必须配合 @Retention?
仅加 @Target 不够,运行时要读取注解信息,还需指定生命周期。通常搭配 @Retention(RetentionPolicy.RUNTIME),否则反射无法获取。
- 如果只用
@Retention(RetentionPolicy.SOURCE),注解仅保留在源码阶段,编译后就丢弃了 - 如果用
CLASS,注解保留在字节码但反射拿不到 - 需要在运行时通过反射检查字段是否带注解,就必须选
RUNTIME
实际校验字段注解的简单示例
配合反射,在运行时检查某个对象的字段是否被标记并做校验:
public static void validate(Object obj) throws IllegalAccessException {
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(NotNull.class)) {
field.setAccessible(true);
Object value = field.get(obj);
if (value == null || (value instanceof String && ((String) value).trim().isEmpty())) {
throw new IllegalArgumentException(field.getName() + " 不能为空");
}
}
}
}
调用时:validate(new User()); 就会检查所有带 @NotNull 的字段值。
常见误用提醒
- 不要写成
@Target({ElementType.FIELD})以外的类型,比如混入METHOD,那就不再“只作用于字段”了 - 不要漏掉
@Retention,否则注解存在但反射看不到 - 字段需设为
accessible才能读取私有字段值,否则会抛IllegalAccessException
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











