@Target + @Retention + isAnnotationPresent + getAnnotation

先把 4 个东西一句话讲清

  1. @Target → 规定注解能贴在哪(类 / 方法 / 变量)
  2. @Retention → 规定注解运行时还活着(必须写)
  3. isAnnotationPresent → 检查有没有贴这个注解(返回 true/false)
  4. getAnnotation → 拿到注解本身,读取里面的值

一、前言:到底什么是注解?

一句话总结:注解就是贴在类、方法、变量上的「特殊标签」。

  • 单纯贴上标签:毫无作用
  • 通过反射扫描读取标签:注解才会产生对应的功能

我们日常使用的 @Override、@SuppressWarnings、Spring的@Controller,本质全部都是注解。

二、四大核心知识点(必学)

自定义注解离不开4个核心部分,我帮你用最简单的语言拆分:

1. @Target(元注解)------ 管控注解【贴在哪里】

作用:给自定义注解制定规则,限制这个标签能粘贴的位置,禁止乱贴。

常用取值(小白只需要背这5个):

  • ElementType.TYPE:可以贴在类、接口、枚举上
  • ElementType.FIELD:可以贴在成员变量上
  • ElementType.METHOD:可以贴在成员方法上
  • ElementType.CONSTRUCTOR:可以贴在构造方法上
  • ElementType.PARAMETER:可以贴在方法参数上

补充:不添加@Target,注解默认可以贴在任意位置。

2. @Retention(元注解)------ 管控注解【活多久】

作用 :控制注解的生命周期,自定义注解想要被反射读取,必须配置它。

三种生命周期:

  • SOURCE:源码阶段有效,编译后直接丢失(如@Override)
  • CLASS:编译阶段有效,运行阶段丢失(默认值)
  • RUNTIME :运行阶段一直存在,唯一能被反射读取(自定义注解必选)

💡 小白铁律:只要是需要自己写、需要读取的自定义注解,无脑写 @Retention(RetentionPolicy.RUNTIME)

3. isAnnotationPresent() ------ 判断【有没有贴标签】

作用:通过反射,判断某个类/方法/变量上是否标注了指定注解。

返回值:布尔类型

  • true:已添加该注解
  • false:未添加该注解

4. getAnnotation() ------ 读取【标签内部数据】

作用:如果已经判断存在注解,通过该方法获取注解对象,进而读取注解内部存储的参数值。

三、完整实战案例(全程可直接运行)

步骤1:自定义注解

定义注解,限制仅能贴在类上,设置运行时永久存活,并自定义两个属性存储数据。

java 复制代码
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

// 规定:该注解只能贴在 类/接口 上
@Target(ElementType.TYPE)
// 规定:运行时存活,支持反射读取
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
    // 自定义注解参数
    String name();
    int age();
}

步骤2:使用注解

在实体类上添加注解,并给注解内部参数赋值。

kotlin 复制代码
// 给User类打上标签,并传入数据
@MyAnno(name = "掘金小白", age = 18)
public class User {
    private String username;
    private String password;
}

步骤3:反射读取注解(核心)

先判断是否存在注解,再获取注解对象、读取内部数据。

arduino 复制代码
public class AnnotationTest {
    public static void main(String[] args) {
        // 1. 获取类的Class对象
        Class<User> clazz = User.class;

        // 2. 判断类上是否存在@MyAnno注解
        boolean isExist = clazz.isAnnotationPresent(MyAnno.class);
        System.out.println("是否添加注解:" + (isExist ? "是" : "否"));

        // 3. 存在注解则读取内部数据
        if(isExist){
            // 获取注解对象
            MyAnno anno = clazz.getAnnotation(MyAnno.class);
            // 读取注解参数
            String name = anno.name();
            int age = anno.age();
            System.out.println("注解存储姓名:" + name);
            System.out.println("注解存储年龄:" + age);
        }
    }
}

步骤4:运行结果

复制代码
是否添加注解:是
注解存储姓名:掘金小白
注解存储年龄:18

四、拓展:注解贴在方法上(补充案例)

修改注解@Target,支持粘贴在方法上,实现方法级别的注解读取。

less 复制代码
// 可贴在类 和 方法上
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnno {
    String name();
    int age();
}

使用+读取:

csharp 复制代码
public class User {
    @MyAnno(name = "测试方法", age = 20)
    public void login(){
        System.out.println("用户登录");
    }
}
ini 复制代码
import java.lang.reflect.Method;

public class AnnotationTest {
    public static void main(String[] args) throws Exception {
        Class<User> clazz = User.class;
        // 获取指定方法
        Method loginMethod = clazz.getMethod("login");

        if(loginMethod.isAnnotationPresent(MyAnno.class)){
            MyAnno anno = loginMethod.getAnnotation(MyAnno.class);
            System.out.println(anno.name());
        }
    }
}

五、终极总结(背诵版)

  1. @Target:约束注解的使用位置,防止注解乱贴
  2. @Retention :设置注解生命周期,自定义注解必须配置 RUNTIME 才能被反射读取
  3. isAnnotationPresent() :做判断,查询目标位置是否存在指定注解
  4. getAnnotation() :获取注解对象,读取注解内部存储的参数

六、极简口诀

Target定位置,Retention保性命; 先判是否存在,再拿注解取值!

相关推荐
陈随易1 小时前
Postman 被曝自动往 Claude Code 和 Codex 装插件
前端·后端·程序员
云-缩影3 小时前
拆解 AI 图像生成应用的后端架构:ECS、OSS 和大模型 API 怎么配合
java·spring boot·后端
考虑考虑4 小时前
Posrgresql恢复.backup文件
数据库·后端·postgresql
无奈何杨5 小时前
风控决策系统决策流,策略模式,权重、顺序、投票、最坏
后端
Patrick_Wilson6 小时前
Go 为什么需要 defer?从函数怎么收尾说起
后端·go·编程语言
苏三说技术6 小时前
DeepSeek Harness入驻B站,评论区被干成了大型插件集市!
后端
橙序员小站6 小时前
我一句话让 AI 把公众号工作台搭完了:部署实测记录
后端
Patrick_Wilson6 小时前
从文本输出理解 Go 方法与接口
后端·go·编程语言
QCoding7 小时前
企业级Agent Evaluation实战:Agent能跑就能上线?AI Agent到底怎么测?
后端·spring
苍何7 小时前
让 WorkBuddy 操控浏览器,干活有点猛啊1
后端