当前位置: 首页 > news >正文

每日八股——java中的注解原理是什么?

Java 注解(Annotation)是 Java 语言引入的一种元数据(Metadata)机制,用于在程序中添加附加信息。虽然注解本身不会直接对代码的执行逻辑产生影响,但它可以通过编译器或运行时工具进行处理,实现一些特殊的行为。

注解的定义

注解的定义类似于接口,通常使用 @interface 关键字来声明。例如:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {String value();
}

注解的组成

  • @Retention:定义注解的生命周期,常见的取值有:
    • RetentionPolicy.SOURCE:只在源码中存在,编译后即被丢弃。
    • RetentionPolicy.CLASS:在编译时被保留,存在于 .class 文件中,但 JVM 运行时不可见。
    • RetentionPolicy.RUNTIME:在运行时保留,JVM 可以读取(通过反射机制)。
  • @Target:定义注解的使用位置(如类、方法、字段等),常见的取值有:
    • ElementType.TYPE:类、接口、枚举
    • ElementType.FIELD:字段(成员变量)
    • ElementType.METHOD:方法
    • ElementType.PARAMETER:参数
    • ElementType.CONSTRUCTOR:构造方法
    • ElementType.ANNOTATION_TYPE:注解
    • ElementType.LOCAL_VARIABLE:局部变量
  • @Inherited:表示注解可以被子类继承。

注解的原理

注解本质上是一种 特殊的接口,所有注解都自动继承自 java.lang.annotation.Annotation 接口。编译器会为注解自动生成相关的字节码,这使得注解能够被编译器、运行时工具或反射机制所处理。

注解的工作机制

1.编译时处理

RetentionPolicy.SOURCE 和 RetentionPolicy.CLASS 类型的注解主要用于静态代码分析和编译时处理工具。

例如,@Override 和 @Deprecated 注解只在编译时生效,它们并不会被编译进 .class 文件。

2.运行时处理

RetentionPolicy.RUNTIME 类型的注解允许在运行时通过 反射(Reflection) 获取注解信息。可以通过 Class、Method、Field 等类的反射方法来读取注解。

import java.lang.annotation.*;
import java.lang.reflect.*;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotation {String value();
}public class Test {@MyAnnotation("Hello, Annotation!")public void myMethod() {System.out.println("This is a test method.");}public static void main(String[] args) throws Exception {Method method = Test.class.getMethod("myMethod");if (method.isAnnotationPresent(MyAnnotation.class)) {MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);System.out.println("Annotation value: " + annotation.value());}}
}

输出

Annotation value: Hello, Annotation!

3. 通过 APT(Annotation Processing Tool)进行编译时注解处理
Java 提供了 APT(Annotation Processing Tool)来在编译时处理注解,通常用于生成代码、配置文件等。可以通过实现 javax.annotation.processing.Processor 接口来自定义注解处理器。

注解的应用场景

  1. 编译时检查:如 @Override、@Deprecated、@SuppressWarnings 等。
  2. 依赖注入(DI):Spring 框架中使用 @Autowired、@Component、@Service 等注解。
  3. AOP(面向切面编程):如 @Transactional、@Aspect 等。
  4. 配置与元数据:如 @Entity、@Table、@Column 等注解用于 ORM 框架(如 Hibernate)。
  5. 序列化与反序列化:如 @JsonProperty、@JsonIgnore 等在 Jackson、Gson 中的使用。

 注解的底层原理

Java 注解在编译后会被存储在 .class 文件中,并且在加载类时会被 JVM 读取。在运行时,可以通过反射机制访问这些注解的元数据。以下是注解在字节码中的表现:

假设有以下注解和类定义:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation {String value();
}@MyAnnotation("test")
public class MyClass {}

使用 javap 工具查看编译后的字节码:

javap -v MyClass.class

输出中会看到类似以下信息:

RuntimeVisibleAnnotations:0: #7(#8=s#9)MyAnnotation(value="test")
  • RuntimeVisibleAnnotations 表示这个注解在运行时是可见的。
  • #7、#8 等是常量池中的索引,用于存储注解的信息。

 小结

  1. 注解是一种元数据机制,主要用于在代码中嵌入信息供工具或框架处理。
  2. 通过反射机制可以在运行时获取注解,这为依赖注入、AOP 等技术提供了灵活的实现方式。
  3. 注解的生命周期和使用目标可以通过 @Retention 和 @Target 进行控制,确保注解的作用范围和可见性符合预期。

http://www.mrgr.cn/news/68249.html

相关文章:

  • 群控系统服务端开发模式-应用开发-本地上传工厂及阿里云上传工厂开发
  • easyexcel实现自定义的策略类, 最后追加错误提示列, 自适应列宽,自动合并重复单元格, 美化表头
  • esp32记录一次错误
  • Java基础——反射
  • 计算机网络:网络层 —— IP 多播技术
  • HarmonyOS使用arkTS拉起指定第三方应用程序
  • C++网络编程之IO多路复用(二)
  • 中阳智能模型的量化投资创新及前景
  • 解决windows server 2016 安装IIS失败问题
  • 【Linux系统编程】第四十三弹---多线程编程指南:线程终止方式与C++11中的thread
  • Vue3+element-plus摘要
  • 全局池化(Global Pooling)
  • css基础:底部固定,导航栏浮动在顶部
  • MyBatis项目的创建和增删查改操作
  • Python中的多线程效率分析
  • metrics
  • 数据库数据恢复—通过拼接数据库碎片恢复 SQL Server 数据库
  • 计算机网络常见面试题(二):浏览器中输入URL返回页面过程、HTTP协议特点,GET、POST的区别,Cookie与Session
  • spark-本地模式的配置和简单使用
  • MQTT应用实例:Air780E模组AT指令的实践!
  • vue2 关闭 Uncaught error 的全屏提示
  • LabVIEW实验室液压制动系统
  • 【Unity】ScriptableObject的应用和3D物体跟随鼠标移动:鼠标放置物体在场景中
  • 无惧任天堂的法律威胁:Switch模拟器Ryujinx v1.2.72版发布
  • C#编程基础:静态成员与实例成员的区别及访问方式
  • 27系统日志查看