注解的原理和解析

关于我

注解的定义

注解(Annotation)是一种用于为代码中的元素(类、方法、变量等)添加元数据的机制。它们不直接参与程序的逻辑操作,但可以在编译时或运行时被读取和处理,以实现特定的功能或行为。

为什么要使用注解

注解的使用有以下几个主要原因:

  1. 代码简洁:通过注解,可以避免大量重复的样板代码,使代码更加简洁易读。
  2. 配置灵活:可以用来替代配置文件,使配置直接与代码绑定,减少了配置的复杂性和维护成本。
  3. 增强功能:结合反射等技术,可以在运行时动态增强代码功能,实现例如依赖注入、事务管理等高级功能。
  4. 文档生成:注解可以用于生成代码文档,帮助开发者理解代码。

注解的分类

注解主要分为三类:

  1. 内置注解:Java内置的注解,如@Override@Deprecated@SuppressWarnings等。
  2. 元注解:用于定义注解的注解,如@Retention@Target@Inherited@Documented
  3. 自定义注解:用户根据需求定义的注解。

注解的定义

定义一个注解很简单,只需使用@interface关键字。例如:

public @interface MyAnnotation {
    String value();
    int number() default 0;
}

元注解语法和使用(文章最后专门重点讲解元注解)

元注解是用于注解其他注解的注解,主要包括:

  1. @Retention:指定注解的保留策略,有SOURCECLASSRUNTIME三种。
  2. @Target:指定注解的作用目标,如METHODFIELDTYPE等。
  3. @Inherited:允许子类继承父类的注解。
  4. @Documented:将注解包含在Javadoc中。

例如:

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

注解运行时的原理

注解在运行时的处理主要依赖于反射机制。通过反射,程序可以在运行时获取类、方法、字段等的注解信息,并根据这些信息执行相应的逻辑。例如,Spring框架中通过注解实现依赖注入,就是在运行时扫描类上的注解,动态创建和注入依赖对象。

Android注解框架

在Android开发中,常用的注解框架包括:

  1. ButterKnife:用于视图绑定和事件绑定。
  2. Dagger:用于依赖注入。
  3. Room:用于数据库操作,简化SQLite的使用。
  4. Retrofit:用于网络请求,结合注解实现接口定义和参数绑定。

编译和运行时注解的解析

注解的解析可以在编译时和运行时进行:

  1. 编译时注解:通过注解处理器(Annotation Processor)在编译期间处理注解,生成代码或进行其他操作。例如,Lombok库通过编译时注解生成getter和setter方法。
  2. 运行时注解:在运行时通过反射获取注解信息并进行处理,例如Spring的依赖注入、JUnit的单元测试框架。
    关于我

说明

  1. 注解本身不直接影响代码的逻辑执行,单独的注解更像是一种标记。它需要结合反射、字节码操作等技术才能发挥作用,实现特定功能。

  2. 注释是给程序员看的,主要用于解释代码。注解则是给编译器或运行时环境看的,用于提供元数据和指示特定的行为。注解本身不会影响代码的正常执行,但它们可以通过元数据的方式间接影响代码的运行。

联系我

元注解(Meta-annotation)是用于注解其他注解的注解。它们在注解的定义和处理过程中起着重要作用。元注解在Java等编程语言中非常常见。以下是Java中的元注解的详细讲解,包括语法和使用示例。

Java中的元注解

Java提供了五种标准的元注解:

  1. @Retention
  2. @Target
  3. @Inherited
  4. @Documented
  5. @Repeatable
1. @Retention

@Retention指定注解的保留策略,它可以有三个值:

  • RetentionPolicy.SOURCE: 注解仅在源代码中保留,编译时会被丢弃。
  • RetentionPolicy.CLASS: 注解在编译时保留在类文件中,但运行时不可见。
  • RetentionPolicy.RUNTIME: 注解在运行时也保留,可以通过反射机制读取。

语法示例

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

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

@Target指定注解可以应用的程序元素类型,比如类、方法、字段等。常见的值有:

  • ElementType.TYPE: 类、接口(包括注解类型)或枚举声明
  • ElementType.FIELD: 字段声明(包括枚举常量)
  • ElementType.METHOD: 方法声明
  • ElementType.PARAMETER: 参数声明
  • ElementType.CONSTRUCTOR: 构造函数声明
  • ElementType.LOCAL_VARIABLE: 局部变量声明
  • ElementType.ANNOTATION_TYPE: 注解类型声明
  • ElementType.PACKAGE: 包声明

语法示例

import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Target({ElementType.METHOD, ElementType.FIELD})
public @interface MyAnnotation {
    String value();
}
3. @Inherited

@Inherited指定某个注解类型是可继承的。如果一个使用了@Inherited修饰的注解类型被用在一个类上,那么这个注解将被用于该类的子类。

语法示例

import java.lang.annotation.Inherited;

@Inherited
public @interface MyInheritedAnnotation {
    String value();
}

@MyInheritedAnnotation(value = "BaseClass")
class BaseClass {
}

class DerivedClass extends BaseClass {
}

在上述示例中,DerivedClass将继承BaseClass@MyInheritedAnnotation注解。

4. @Documented

@Documented指定使用这个注解的元素应该被javadoc或类似工具记录。默认情况下,注解是不包括在javadoc中的。

语法示例

import java.lang.annotation.Documented;

@Documented
public @interface MyDocumentedAnnotation {
    String value();
}
5. @Repeatable

@Repeatable允许同一个注解在同一个元素上使用多次。Java 8引入了这个功能。

语法示例

import java.lang.annotation.Repeatable;

@Repeatable(MyAnnotations.class)
public @interface MyAnnotation {
    String value();
}

public @interface MyAnnotations {
    MyAnnotation[] value();
}

@MyAnnotation("First")
@MyAnnotation("Second")
public class MyClass {
}

使用示例

综合以上元注解,以下是一个完整的示例,展示如何定义和使用自定义注解。

定义注解

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;

// @MyAnnotation 可以在方法和字段上使用,保留到运行时,记录在javadoc中,并且可继承和重复使用
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
@Repeatable(MyAnnotations.class)
public @interface MyAnnotation {
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface MyAnnotations {
    MyAnnotation[] value();
}

使用注解

@MyAnnotation("First")
@MyAnnotation("Second")
public class AnnotatedClass {

    @MyAnnotation("Field Annotation")
    private String myField;

    @MyAnnotation("Method Annotation")
    public void myMethod() {
    }
}

public class Test {
    public static void main(String[] args) {
        // 反射获取注解信息
        Class<AnnotatedClass> obj = AnnotatedClass.class;

        // 检查类上的注解
        if (obj.isAnnotationPresent(MyAnnotations.class)) {
            MyAnnotations annotations = obj.getAnnotation(MyAnnotations.class);
            for (MyAnnotation annotation : annotations.value()) {
                System.out.println(annotation.value());
            }
        }
        
        // 检查字段上的注解
        try {
            java.lang.reflect.Field field = obj.getDeclaredField("myField");
            if (field.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation annotation = field.getAnnotation(MyAnnotation.class);
                System.out.println(annotation.value());
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        // 检查方法上的注解
        try {
            java.lang.reflect.Method method = obj.getDeclaredMethod("myMethod");
            if (method.isAnnotationPresent(MyAnnotation.class)) {
                MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
                System.out.println(annotation.value());
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}

联系我

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/781869.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络性能指标概述:速率、带宽、时延等

在计算机网络中&#xff0c;性能指标是衡量网络效率和质量的重要参数。本文将综合三篇关于计算机网络性能指标的文章&#xff0c;详细介绍速率、带宽、吞吐量、时延、时延带宽积、往返时延&#xff08;RTT&#xff09; 和利用率的概念及其在网络中的应用。 1. 速率&#xff08;…

windows系统本地端口被占用的问题

第一步&#xff1a;查找所有运行的端口 按住“WindowsR”组合键&#xff0c;打开命令窗口&#xff0c;输入【cmd】命令&#xff0c;回车。在弹出的窗口中输入 命令【netstat -ano】&#xff0c;再按一下回车键 Win系统端口被占用-查找所有运行的端口 第二步&#xff1a;查看…

整洁架构SOLID-单一职责原则(SRP)

文章目录 定义案例分析重复的假象代码合并解决方案 小结 定义 SRP是SOLID五大设计原则中最容易被误解的一个。也许是名字的原因&#xff0c;很多程序员根据SRP这个名字想当然地认为这个原则就是指&#xff1a;每个模块都应该只做一件事。 在历史上&#xff0c;我们曾经这样描…

CSS技巧:纯CSS实现文字渐变动画效果

文字渐变动画&#xff0c;可以实现的有两种&#xff1a;一种是一行文字整体变化颜色&#xff1b;另一种一行文字依次变化颜色。接下来&#xff0c;我就介绍一下这两种文字渐变的实现过程。 布局代码&#xff1a; <div class"con"><div class"animate…

GPIO配置-PIN_Speed的理解

在使用STM32的GPIO 口配置时&#xff0c;经常会疑惑应该选用什么样的配置模式&#xff0c;本文谈谈对pin_speed的理解。 根据数据手册可得&#xff0c;STM32提供10MHz,2MHz和50MHz三种输出速度的配置&#xff0c;三种配置的应用场景是怎么样的&#xff1f;。 1.为什么要配置引…

力扣双指针算法题目:快乐数

目录 1.题目 2.思路解析 3.代码展示 1.题目 . - 力扣&#xff08;LeetCode&#xff09; 2.思路解析 题目意思是将一个正整数上面的每一位拿出来&#xff0c;然后分别求平方&#xff0c;最后将这些数字的平方求和得到一个数字&#xff0c;如此循环&#xff0c;如果在此循环中…

OpenEarthMap:全球高分辨率土地覆盖制图的基准数据集(开源来下载!!!)

OpenEarthMap由220万段5000张航拍和卫星图像组成&#xff0c;覆盖6大洲44个国家97个地区&#xff0c;在0.25-0.5m的地面采样距离上人工标注8类土地覆盖标签。我们提供8类标注:裸地、牧场、已开发空间、道路、树木、水、农业用地和建筑。类选择与现有的具有亚米GSD的产品和基准数…

C#知识|项目的实施过程及通用三级架构的搭建笔记

哈喽,你好啊,我是雷工! 01 项目需求分析 根据与需求方沟通,分析需求,一般都有需求分析师来进行项目需求收集与分析。 根据需求文档进行项目功能设计。 02 框架的选择 ①小项目可以根据需求选择两层或三层结构。 ②中型大型项目,至少需要三层架构和其他架构的组合。 03 框…

ESP32 步进电机精准控制:打造高精度 DIY 写字机器人,实现流畅书写体验

摘要: 想让你的 ESP32 不再仅仅是控制灯光的工具吗&#xff1f; 本文将带你使用 ESP32 开发板、步进电机和简单的机械结构打造一个能够自动写字的机器人。我们将深入浅出地讲解硬件连接、软件代码以及控制逻辑&#xff0c;并提供完整的项目代码和电路图&#xff0c;即使是 Ardu…

使用握手信号实现跨时钟域数据传输

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 参考代码 描述 分别编写一个数据发送模块和一个数据接收模块&#xff0c;模块的时钟信号分别为clk_a&#xff0c;clk_b。两个时钟的频率不相同。数据发送模块循环发送0-7&#xff0c;在每个数据传输完成之后&#xf…

六、数据可视化—首页、列表页制作(爬虫及数据可视化)

六、数据可视化—首页、列表页制作&#xff08;爬虫及数据可视化&#xff09; 1&#xff0c;首页制作&#xff08;1&#xff09;创建新项目选择flask框架&#xff08;2&#xff09;下载模板&#xff08;3&#xff09;导入flask框架中进行改写&#xff08;4&#xff09;访问服务…

puppeteer 爬虫初探

1. puppeteer 和 puppeteer-core 安装 puppeteer 会默认下载一个最新版本的 chrome 浏览器&#xff1b; 安装 puppeteer-core &#xff0c;不会安装 chrome, 若要程序打开浏览器运行时&#xff0c;需手动指定电脑系统安装的 chrome 浏览器路径&#xff1b; 2. puppeteer-core …

某大会的影响力正在扩大,吞噬了整个数据库世界!

1.规模空前 你是否曾被那句“上有天堂&#xff0c;下有苏杭”所打动&#xff0c;对杭州的湖光山色心驰神往&#xff1f;7月&#xff0c;正是夏意正浓的时节&#xff0c;也是游览杭州的最佳时期。这座古典与现代交融的城市将迎来了第13届PostgreSQL中国技术大会。作为全球数据库…

禁用windows的语音识别快捷键win+ctrl+s

win11组合键winctrls会弹出语音识别提示&#xff0c;即使到设置里禁用了语音识别也没用 解决办法&#xff1a;安装PowerToys&#xff0c;通过“键盘管理器”-“重新映射快捷键”禁用 PowerToys是微软自己的工具&#xff0c;不用担心安全问题&#xff0c;下载地址&#xff1a;h…

昇思25天学习打卡营第9天|静态图模式的深度剖析与应用指南

目录 背景介绍 动态图模式 静态图模式 静态图模式的使用场景 静态图模式开启方式 基于装饰器的开启方式 基于context的开启方式 静态图的语法约束 JitConfig配置选项 静态图高级编程技巧 背景介绍 AI 编译框架主要包含两种运行模式&#xff0c;即动态图模式与静态图模…

解决GPT-4o耗电难题!DeepMind新算法训练效率提升13倍,能耗降低10倍!

目录 01 有更好的解决方案吗&#xff1f; 02 从“超级batch”中筛选数据 03 技术介绍 04 实验结果 生成可学习batch 谷歌DeepMind推出的新算法JEST&#xff0c;将LLM训练的迭代次数减少了13倍&#xff0c;计算量降低了10倍&#xff0c;有望重塑AI未来。GPT-4o早已成为耗能…

python破解字母已知但大小写未知密码

python穷举已知字符串中某个或多个字符为大写的所有情况 可以使用递归函数来实现这个功能。以下是一个示例代码&#xff1a; def generate_uppercase_combinations(s, index0, current):if index len(s):print(current)returngenerate_uppercase_combinations(s, index 1, …

Debezium报错处理系列之第109篇:解决升级日志解析jar包重启集群出现的字段类型和值不匹配的错误

Debezium报错处理系列之第109篇:解决升级日志解析jar包重启集群出现的字段类型和值不匹配的错误 一、完整报错二、错误原因三、解决方法Debezium从入门到精通系列之:研究Debezium技术遇到的各种错误解决方法汇总: Debezium从入门到精通系列之:百篇系列文章汇总之研究Debezi…

Educational Codeforces Round 167 (Rated for Div. 2)(A~C)题解

A. Catch the Coin 解题思路: 最终&#x1d465;一定会相等&#xff0c;我们考虑直接到下面接住他。 #include<bits/stdc.h> using namespace std; typedef long long ll; #define N 1000005 ll dp[N], w[N], v[N], h[N]; ll dis[1005][1005]; ll a, b, c, n, m, t; ll…

【数据结构与算法】希尔排序

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《数据结构与算法》 期待您的关注 ​