注解的原理和解析

关于我

注解的定义

注解(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.mzph.cn/pingmian/42647.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Koa2实现多并发文件上传

koa2批量上传文件 目前的是为了实现批量导入md文件&#xff0c;发布文章。这样就不用自己一篇一篇同步文章了。一次可以同步几千篇文章。 实现界面 内容 主要包含上传的文件标题&#xff0c;文件大小&#xff0c;上传状态。 <el-upload ref"uploader" v-model:…

Vue笔记12-新的组件

Fragment 在Vue2中&#xff0c;template标签内&#xff0c;必须有一个div标签&#xff0c;作为根标签。 在Vue3中&#xff0c;可以没有div根标签&#xff0c;如果没有的话&#xff0c;Vue3会将多个标签包装在一个Fragment虚拟元素里。 这么做的目的&#xff1a;减少标签的层级…

【Java12】封装

封装&#xff08;Encapsulation&#xff09;是面向对象的三大特征之一&#xff08;另两个是继承和多态&#xff09;&#xff0c;指的是将对象的状态信息隐藏在对象内部&#xff0c;不允许外部程序直接访问对象的内部信息&#xff0c;而是通过该类所提供的方法来实现对内部信息的…

java入门3-java语法基础学习(类型转换)

&#xff08;一 &#xff09;自动类型转换 (1)类型范围小的变量可以直接赋值给类型范围大的变量 //自动类型转换执行原理 byte a12; a:00001100 (byte:8位的二进制) int ba; b:00000000 00000000 00000000 00001100 (int&a…

2024中期业绩预告

股票简称业绩预告类型业绩预告摘要净利润变动幅度(%)上年同期净利润(元)公告日期业绩变动原因报告期内公司所处行业情况报告期内公司从事的主要业务核心竞争力分析备注湖北宜化业绩大幅上升净利润51000万元至57000万元;增长幅度为102.09%至125.87%125.872.52亿7/8/2024预计2024…

找不到x3daudio1_7.dll怎么修复?一招搞定x3daudio1_7.dll丢失问题

当你的电脑突然弹出提示&#xff0c;“找不到x3daudio1_7.dll”&#xff0c;这时候你就需要警惕了。这往往意味着你的电脑中的程序出现了问题&#xff0c;你可能会发现自己无法打开程序&#xff0c;或者即便打开了程序也无法正常使用。因此&#xff0c;接下来我们要一起学习一下…

小程序 使用 UI 组件 Vant Weapp 、vant组件样式覆盖

注意&#xff1a;使用vant 包&#xff0c;需要把app.json 中 的"style:v2" 这句去掉 不然会出现样式混乱的问题 Vant Weapp组件库的使用 参考官网 vant官网 Vant Weapp 组件样式覆盖 Vant Weapp 基于微信小程序的机制&#xff0c;为开发者提供了 3 种修改组件样式…

深入了解Linux中的udhcpc:动态主机配置协议客户端

目录 什么是udhcpc&#xff1f;安装udhcpc配置网络接口使用udhcpc获取IP地址配置静态IP地址自定义udhcpc脚本高级选项udhcpc常见问题及排查方法1. 无法获取IP地址2. DNS配置不正确3. IP地址冲突4. 无法连接到默认网关5. 无法执行自定义脚本 在Linux系统中&#xff0c;网络配置是…

[数据结构] --- 线性数据结构(数组/链表/栈/队列)

1 线性结构和非线性结构的理解 1.1 线性结构 线性结构是什么&#xff1f; 数据结构中线性结构指的是数据元素之间存在着“一对一”的线性关系的数据结构。线性结构是一个有序数据元素的集合。 线性结构特点&#xff1a; 线性结构有唯一的首元素&#xff08;第一个元素&#…

leetcode力扣_贪心思想

455.分发饼干&#xff08;easy-自己想得出来并写好&#xff09; 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺…

【CUDA】

笔者在学习Softmax实现时遇到了一个问题&#xff0c;很多文章直接将softmax的计算分成了五个过程&#xff0c;而没有解释每个过程的含义&#xff0c;尤其是在阅读这篇文章时&#xff0c;作者想计算最基本的softmax的效率&#xff0c;以展示可行的优化空间&#xff1a; 贴一个g…

前端html面试常见问题

前端html面试常见问题 1. !DOCTYPE (文档类型)的作用2. meta标签3. 对 HTML 语义化 的理解&#xff1f;语义元素有哪些&#xff1f;语义化的优点4. HTML中 title 、alt 属性的区别5. src、href 、url 之间的区别6. script标签中的 async、defer 的区别7. 行内元素、块级元素、空…

【python教程】数据分析——numpy、pandas、matplotlib

【python教程】数据分析——numpy、pandas、matplotlib 文章目录 什么是matplotlib安装matplotlib&#xff0c;画个折线 什么是matplotlib matplotlib:最流行的Python底层绘图库&#xff0c;主要做数据可视化图表,名字取材于MATLAB&#xff0c;模仿MATLAB构建 安装matplotlib&…

AI教你如何系统的学习Python

Python学习计划 第一阶段&#xff1a;Python基础&#xff08;1-2个月&#xff09; 目标&#xff1a;掌握Python的基本语法、数据类型、控制结构、函数、模块和包等。 学习Python基本语法&#xff1a;包括变量、数据类型&#xff08;整数、浮点数、字符串、列表、元组、字典、…

5款屏幕监控软件精选|电脑屏幕监控软件分享

屏幕监控软件在现代工作环境中扮演着越来越重要的角色&#xff0c;无论是为了提高员工的工作效率&#xff0c;还是为了保障企业数据的安全&#xff0c;它们都成为了不可或缺的工具。 下面&#xff0c;让我们以一种新颖且易于理解的方式&#xff0c;来介绍五款备受好评的屏幕监…

XGBoost模型中参数stratify的作用

目录 1.参数stratify的作用2.代码演示3. 为什么XGBoost从分类模型转成回归模型&#xff0c;这个参数要去掉呢? 1.参数stratify的作用 在使用XGBoost进行分类任务时&#xff0c;数据集通常会被分成训练集和测试集。为了确保训练集和测试集中的类分布与原始数据集中的类分布一致…

蚁剑编码器编写——中篇

看第二个示例 hex编码 木马 <?php foreach($_POST as $k > $v){$_POST[$k]pack("H*", $v);} eval($_POST[ant]); ?>pack(“H*”, $v)是将 $v 转换为为二进制&#xff0c;也就是ASCII解码 编码器 module.exports (pwd, data) > {let ret {};for (…

J023_用正则表达式爬取信息

一、需求描述 请把下面文本中的电话、邮箱、座机号码和热线都爬取出来&#xff1a; 来黑马程序员学习Java&#xff0c;电话&#xff1a;18512566758&#xff0c;18354678765&#xff1b;或者联系邮箱&#xff1a;boniuitcast.cn&#xff1b;座机电话&#xff1a;010365178955…

Spring cloud 中使用 OpenFeign:让 http 调用更优雅

注意&#xff1a;本文演示所使用的 Spring Cloud、Spring Cloud Alibaba 的版本分为为 2023.0.0 和 2023.0.1.0。不兼容的版本可能会导致配置不生效等问题。 1、什么是 OpenFeign Feign 是一个声明式的 Web service 客户端。 它使编写 Web service 客户端更加容易。只需使用 F…

Guitar Pro8.2让你的吉他弹奏如虎添翼!

亲爱的音乐爱好者们&#xff0c;今天我要跟大家安利一个让我彻底沉迷其中的神器——Guitar Pro8.2&#xff01;这可不是一般的软件&#xff0c;它简直是吉他手们的福音。不管你是初学者还是老鸟&#xff0c;这个打谱软件都能给你带来前所未有的便利和价值。 让我们来聊聊Guita…