Java 注解(Annotation)

📅 2026/7/11 20:15:49 👁️ 阅读次数 📝 编程学习
Java 注解(Annotation)

1. 什么是注解?

注解(Annotation),也叫注释类型,是一种引用数据类型。它和类、接口一样,编译后也会生成.class文件。

注解本身不直接改变程序逻辑,但它可以携带元数据,在编译、类加载、运行时被读取,并配合工具或框架完成特定功能。

2. 自定义注解的语法

自定义注解使用@interface关键字,基本语法如下:

[修饰符列表]@interface注解类型名{// 属性定义}

使用注解的语法格式

@注解类型名

注解可以出现的位置

  • 类上(上一行)
  • 属性上
  • 方法上
  • 变量上
  • 甚至可以用在注解上

3. JDK 内置注解

java.lang包下提供了几个常用的内置注解:

3.1 @Deprecated

@Deprecated用于标记不推荐使用的程序元素。通常是因为该元素存在危险,或者已有更好的替代方案。

3.2 @Override

@Override表示一个方法声明意图重写父类中的方法。

核心要点

  • 只能注解方法
  • 仅供编译器参考,与运行时无关
  • 编译器会检查被标注的方法是否确实是重写父类方法,不是则报错

3.3 @SuppressWarnings

@SuppressWarnings用于指示编译器取消显示指定的警告信息。

4. 元注解

元注解是专门用来标注其他注解的注解。

4.1 @Target

@Target指定被标注的注解可以出现在哪些程序元素上。例如:

@Target(ElementType.METHOD)

表示被该注解标注的自定义注解只能出现在方法上。

4.2 @Retention

@Retention指定被标注的注解最终保留到哪个阶段。取值如下:

取值含义
RetentionPolicy.SOURCE仅保留在 Java 源文件中
RetentionPolicy.CLASS保留在 class 文件中,但 JVM 不加载
RetentionPolicy.RUNTIME保留在 class 文件中,且能被反射机制读取

@Retention的源码

public@interfaceRetention{RetentionPolicyvalue();}publicenumRetentionPolicy{SOURCE,CLASS,RUNTIME}

@Target的源码

public@interfaceTarget{ElementType[]value;// ElementType 是一个枚举}

5. 注解中定义属性

在注解中可以定义属性,语法与方法类似:

public@interfaceMyAnnotation{Stringname();// 属性 nameString[]color();// 属性 color,数组类型intage()default18;// 属性 age,指定默认值后使用时可以不赋值int[]no;// 属性 no,数组类型}

使用规则

  • 如果注解中有属性,使用时必须给属性赋值(已指定默认值的除外)
  • 数组属性只有一个元素时,可以省略花括号{}
publicclassTest{@MyAnnotation(name="zhangsan",color={"blue","red"},no=1)publicvoiddoSomething(){// age 有默认值,可写可不写}}

5.1 属性名为 value 的特殊规则

如果属性名为value,且只有这一个属性时,使用注解可以省略属性名:

public@interfaceMyAnnotation01{Stringvalue();}publicclassTest01{@MyAnnotation01("haha")publicvoiddoSomething(){}}

如果有多个属性,则value也必须显式写出属性名。

5.2 属性支持的类型

注解属性可以是以下类型及其数组形式:

  • 基本数据类型(int、double、boolean 等)
  • String
  • Class
  • 枚举
  • 以上类型的数组

6. 通过反射获取注解

注解可以通过反射机制在运行时读取,前提是@Retention必须设置为RUNTIME

// 获取类的 Class 对象Classc=Class.forName("完整类名");// 判断该类上是否存在指定注解System.out.println(c.isAnnotationPresent(注解类型名.class));if(c.isAnnotationPresent(注解类型名.class)){// 获取注解对象注解类名 对象名=(注解类型名)c.getAnnotation(注解类型名.class);// 读取注解属性值,就像调用接口方法一样对象名.属性名();}

通过反射与注解的配合,可以在运行时动态获取类、方法、字段上的元数据,这是 Spring、JUnit 等框架的核心机制之一。