@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保性命; 先判是否存在,再拿注解取值!

相关推荐
黄同学real2 小时前
HJL WebAPI 项目日志入库实战:从建表到自动清理
后端
孟陬2 小时前
国外技术周刊 #140:在 Jeff Bezos 的私密 Campfire 峰会上,我学到了关于亿万富翁的事
前端·后端
小闹5492 小时前
CLAUDE CODE生成可视化数据库工具
后端
星星电灯猴2 小时前
全面解决Charles抓取HTTPS请求响应中文乱码问题的方法与技巧
后端·ios
道友可好3 小时前
写给 AI 的入职手册,AGENTS.md
前端·人工智能·后端
sandnes3 小时前
把ToolUse循环做到生产级-错误处理与可靠性五件套
后端
掘金者阿豪3 小时前
全维度拆解具身智能:底层技术 + 实战落地 + 全球产业竞争
后端
秋天的一阵风3 小时前
✨ 代码秒跳转、自动补全?全靠 LSP 和 AST!
前端·后端·ai编程
用户298698530143 小时前
Java 中的 HTML 解析:从文件读取、URL 抓取到数据提取
java·后端