JavaSE : 注解 Annotation

注解

Java中的注解(Annotation)是一种元数据形式,用于向编译器或JVM提供有关程序元素(如类、方法、变量、参数和包)的附加信息。注解不会直接影响程序的行为或结构,但它们可以被编译器、开发工具或运行时环境用于生成代码、进行验证、执行处理或提供信息。以下是关于Java注解的几个关键点:

1. 注解的种类

1.1.内置标准注解

  • @Override:指示一个方法覆盖了超类中的方法。
  • @Deprecated:标记已过时的元素,建议不再使用。
  • @SuppressWarnings:抑制编译器警告。

1.2.元注解:给注解用的注解

用于创建自定义注解的注解,包括:

1.2.1.@Retention

指定注解保留策略(解析时间),如RetentionPolicy.SOURCE(只保留在源码中)、RetentionPolicy.CLASS(保留在class文件中)或RetentionPolicy.RUNTIME(运行时可通过反射访问)。

1.2.1.1. SOURCE : 编译时(Compile Time)

编译时解析的注解在源代码被编译成字节码时被处理。这些注解主要用于生成额外的代码、检查代码的正确性或进行其他静态分析。例如,@Override, @Deprecated, 和一些编译器使用的注解如Lombok的@Data就是在编译时期被解析的。编译器或注解处理器(如APT, Annotation Processing Tool)会读取这些注解并据此执行相应的操作。

1.2.1.2.CLASS : 类加载时(Class Load Time)

这类注解在类被加载到Java虚拟机(JVM)时被解析。例如,一些框架或库会在类加载阶段利用这些注解来配置类的行为,如Spring框架使用@Component, @Service, @Autowired等注解来实现依赖注入和bean的装配,这些注解会在应用上下文初始化,即类加载时被解析和处理。

1.2.1.3.RUNTIME : 运行时(Runtime)

运行时解析的注解在应用程序运行过程中可以被读取和处理。这意味着注解信息在程序执行期间始终可用,可以通过反射API来访问这些注解。例如,@Retention(RetentionPolicy.RUNTIME)注解的那些注解可以在程序运行时通过反射被检测到,常用于自定义注解处理、日志记录、权限控制等场景。

1.2.2.@Target

指定注解可以应用到哪些程序元素上。

它接受一个ElementType类型的枚举值数组作为参数,ElementType枚举定义了一系列可能的目标元素类型。以下是ElementType的一些主要选项:

  1. ElementType.TYPE: 类、接口(包括注解类型)或枚举声明。
  2. ElementType.FIELD: 类或接口中的字段声明(包括枚举常量)。
  3. ElementType.METHOD: 类或接口中的方法声明。
  4. ElementType.PARAMETER: 方法参数声明。
  5. ElementType.CONSTRUCTOR: 类的构造函数声明。
  6. ElementType.LOCAL_VARIABLE: 本地变量声明。
  7. ElementType.ANNOTATION_TYPE: 另一个注解的声明。
  8. ElementType.PACKAGE: 包声明。
  9. ElementType.TYPE_PARAMETER: 类型参数声明(Java 8及以后版本)。
  10. ElementType.TYPE_USE: 任何类型使用的地方,如泛型参数、类型转换、静态成员的类型等(Java 8及以后版本)。

1.2.3.@Documented

指示该注解应被包含在生成的API文档中。

1.2.4.@Inherited

允许子类继承父类上的注解。

1.2.5.@Repeatable

自Java 8起,允许同一注解在同一声明上多次使用。

1.3.自定义注解

开发者可以定义自己的注解,通过@interface关键字实现,用于满足特定的编程需求或框架集成。

public @interface MyAnnotation {}

1.3.1.注解的参数

定义注解参数

  1. 参数类型:注解参数必须是基本类型、String、Class、枚举类型、注解类型或者这些类型的数组。不能使用其他复杂类型如自定义类作为参数。

  2. 默认值:每个注解参数都可以有一个默认值,如果没有提供默认值且该参数又是必需的,则在使用注解时必须显式指定参数值。

  3. 参数命名:参数命名遵循Java的标识符规则,通常采用小驼峰命名法。

示例定义

public @interface MyAnnotation {String name() default "";      // 默认值为空字符串int age();                    // 必须提供值,没有默认值Class<?> clazz() default Object.class; // 默认值为Object类ElementType[] targets();       // 参数可以是数组类型
}

使用注解参数

在应用注解时,通过参数名指定参数值,如果是数组类型的参数,可以使用花括号 {} 来包裹多个值。

@MyAnnotation(name = "Alice", age = 25, clazz = String.class, targets = {ElementType.FIELD, ElementType.METHOD})
public class MyClass {// ...
}

特殊参数类型

  • Class类型参数:允许指定一个类或接口类型。
  • 枚举类型参数:限制参数为预定义的一组值。
  • 注解类型参数:允许注解作为参数,用于嵌套注解的情况。
  • 数组类型参数:支持传递多个相同类型的值,如上面的targets参数。

1.3.2.value参数

在Java注解中,value是一个特殊的参数名。当一个注解只有一个参数,并且该参数名为value时,你可以省略参数名直接指定值。这种设计让注解的使用更加简洁易读。下面是具体说明和示例:

特殊之处

  • 默认识别:如果一个注解仅定义了一个参数,并且这个参数的名字是value,那么在使用该注解时,可以直接写值而不必指定参数名。编译器会自动将这个值赋给value参数。
  • 多参数注解中的value : 即使一个注解定义了多个参数,如果其中包含名为value的参数,你仍然可以在只有一个值需要传递时省略value=。但是,如果有多个值需要指定,则所有参数都必须明确指出参数名。

示例定义

public @interface MySingleValueAnnotation {String value(); // 注意这里只有一个名为value的参数
}

使用示例

@MySingleValueAnnotation("Some text") // 直接写值,不需要写value=
public class MyClass {// ...
}// 对于非字符串或基本类型,同样适用
@MySingleValueAnnotation(123) // 假设value参数类型为int
public void myMethod() {// ...
}

2.访问注解信息

在Java中,通过反射处理注解是一种常见的做法,主要用于在运行时 ( 即使用@Retention(RUNTIME)定义的注解 ) 动态地检查和操作那些被注解标记的类、方法、字段等元素。以下是一些基本步骤和示例,展示如何使用反射来获取和使用注解信息:

2.1. 获取注解实例

首先,你需要获取到你想要检查的类、方法或字段的 Class 对象。之后,可以使用这个 Class 对象提供的几个方法来检查和获取注解:

  • isAnnotationPresent(Class<? extends Annotation> annotationClass):检查是否具有指定类型的注解。
  • getAnnotation(Class<? extends Annotation> annotationClass):获取指定类型的注解实例,如果没有则返回 null
  • getAnnotations()getDeclaredAnnotations():获取所有注解或直接声明的注解数组。

示例:获取类上的注解

假设我们有一个自定义的注解 @MyAnnotation,并应用到了某个类 MyClass 上。

@MyAnnotation(value = "Hello, World!")
public class MyClass {// ...
}

获取这个类上的 MyAnnotation 实例:

Class<MyClass> clazz = MyClass.class;
if (clazz.isAnnotationPresent(MyAnnotation.class)) {MyAnnotation myAnnotation = clazz.getAnnotation(MyAnnotation.class);System.out.println("注解的值: " + myAnnotation.value());
}

示例:获取方法上的注解

同样的,如果 MyAnnotation 应用于某个方法上:

public class MyClass {@MyAnnotation(value = "Method Annotation")public void myMethod() {// ...}
}

获取方法上的注解:

Method method = MyClass.class.getMethod("myMethod");
if (method.isAnnotationPresent(MyAnnotation.class)) {MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);System.out.println("方法注解的值: " + myAnnotation.value());
}

示例:基于注解值动态操作

根据注解的信息,你可以进一步决定程序的执行逻辑,例如:

if (myAnnotation != null && "Special Value".equals(myAnnotation.value())) {// 执行特定的操作
} else {// 执行默认操作
}

注意事项

  • 确保你的注解有运行时保留策略 (@Retention(RetentionPolicy.RUNTIME)),否则它们不会在运行时可见。
  • 当使用反射处理注解时,考虑性能影响,特别是在频繁操作或大型项目中。
  • 利用注解可以极大地增强代码的灵活性和可配置性,但过度使用或设计不当也可能导致代码难以理解和维护。

3. 注解的作用

  • 提供配置信息:注解可以替代XML或其他外部配置文件,直接在代码中提供配置细节。
  • 代码文档化:增强代码的自我解释性,提供方法用途、参数意义等信息。
  • 编译时检查:通过编译时注解处理器进行类型安全检查、格式验证等。
  • 框架集成:许多Java框架(如Spring)使用注解来配置依赖注入、事务管理等。
  • 代码生成:一些工具可以读取注解并据此自动生成代码片段,如序列化/反序列化代码、getter/setter等。
  • 运行时处理:通过反射,应用程序可以在运行时发现和处理注解,实现动态行为。

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

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

相关文章

Apache CXF Aegis databinding SSRF 高危漏洞修复

一、漏洞修复 Apache CXF Aegis databinding SSRF漏洞 Spring Web UriComponentsBuilder URL解析不当漏洞 二、修复步骤 1、Apache CXF Aegis databinding SSRF漏洞修复 步骤&#xff1a; 进入服务器搜索 databinding find -name *databinding* 发现版本是3.1.6 果断…

数据结构~~带环链表的环开始的节点位置**两种方法

1.带环链表环开始的位置 &#xff08;1&#xff09;上面的这个测试用例使用的是包含了4个节点的带环链表&#xff0c;我们要找的就是链表里面的环开始的节点的位置&#xff0c;拿这个测试用例而言&#xff0c;就是2这个节点&#xff0c;从这个节点开始&#xff0c;我们的链表就…

【第16章】MyBatis-Spring之SqlSession

文章目录 前言一、SqlSessionTemplate1. 创建2. 使用3. 批量操作3.1 创建SqlSessionTemplate3.2 service3.3 controller 二、SqlSessionDaoSupport总结 前言 在 MyBatis 中&#xff0c;你可以使用 SqlSessionFactory 来创建 SqlSession。 一旦你获得一个 session 之后&#xf…

源码部署EFK

目录 资源列表 基础环境 关闭防护墙 关闭内核安全机制 修改主机名 添加hosts映射 一、部署elasticsearch 修改limit限制 部署elasticsearch 修改配置文件 单节点 集群(3台节点集群为例) 启动 二、部署filebeat 部署filebeat 添加配置文件 启动 三、部署kiban…

单点登录【demo】

前言 2023-07-29 15:44:56 公开发布于 2024-5-22 00:04:56 单点登录【demo】 以下是 Java 实现单点登录的示例代码&#xff1a; 单点登录&#xff08;Single Sign-On&#xff0c;SSO&#xff09;是一种身份认证和授权机制&#xff0c;可以使用户在多个应用程序或系统之间使…

SQL常用基础语句(一)-- FGHIJ开头

GROUP BY GROUP BY语法可以根据给定数据列的每个成员对查询结果进行分组统计&#xff0c;最终得到一个分组汇总表。在GROUP BY子句后面包含了一个HAVING子句&#xff0c;HAVING类似于WHERE&#xff0c;&#xff08;唯一的差别是WHERE过滤行&#xff0c;HAVING过滤组&#xff0…

【C/C++笔试练习】TCP、IP广播、ARP协议、IP路由器、MAC协议、三次握手、TCP/IP、子网划分年、会抽奖、抄送列表

文章目录 C/C笔试练习选择部分&#xff08;1&#xff09;TCP&#xff08;2&#xff09;IP广播&#xff08;3&#xff09;ARP协议&#xff08;4&#xff09;IP路由器&#xff08;5&#xff09;MAC协议&#xff08;6&#xff09;三次握手&#xff08;7&#xff09;TCP/IP&#xf…

PHP在线制作表白网源码

PHP在线制作表白网源码&#xff0c;送女友个惊喜吧&#xff0c;无数据库&#xff0c;上传就能用&#xff0c;后台/admin&#xff0c;账号密码都是admin 百度网盘&#xff1a;https://pan.baidu.com/s/1rbD2_8IsP9UPLK-cdgEXfA?pwdre59

AWS安全性身份和合规性之Secrets Manager

AWS Secrets Manager是一项AWS托管的服务&#xff0c;用于安全地存储、管理和轮转敏感信息&#xff0c;如数据库密码、API密钥、OAuth令牌等。AWS Secrets Manager助您在整个生命周期内轻松管理、检索和轮换数据库凭证、API密钥和其他密钥。 关键词&#xff1a;集中管理、加密…

sql使用加和进行合并去重并提升速率

背景 有三张表ltd1 、ltd0051和、ltd0011ltd1作为主表&#xff0c;左关联 ltd0051和ltd0011如果ltd0051有两条重复数据、td0011有两条重复数据&#xff0c;左关联之后就会得到4条&#xff0c;同时ltd0051和ltd0011这两条数据都是正确&#xff0c;基于主键我们需要将两个相同主键…

【全开源】AJAX家政上门服务系统小程序自营+多商家(高级授权)+独立端

基于FastAdmin和原生微信小程序开发的一款同城预约、上门服务、到店核销家政系统&#xff0c;用户端、服务端(高级授权)、门店端(高级授权)各端相互依赖又相互独立&#xff0c;支持选择项目、选择服务人员、选择门店多种下单方式&#xff0c;支持上门服务和到店核销两种服务方式…

深入理解数仓开发(一)数据技术篇之日志采集

前言 今天开始重新回顾电商数仓项目&#xff0c;结合《阿里巴巴大数据之路》和尚硅谷的《剑指大数据——企业级电商数据仓库项目实战 精华版》来进行第二次深入理解学习。之前第一次学习数仓&#xff0c;虽然尽量放慢速度力求深入理解&#xff0c;但是不可能一遍掌握&#xff0…

我在去哪儿薅到了5块钱火车票代金券,速薅

哈哈&#xff0c;亲爱的薅羊毛小伙伴们&#xff01; 刚刚在去哪儿大佬那儿发现了一个超级薅羊毛福利&#xff01;我只花了短短两分钟&#xff0c;就搞到了一张5块钱火车票代金券&#xff0c;简直是天上掉馅饼的节奏啊&#xff01; 话不多说&#xff0c;薅羊毛的姿势给你们摆好…

代码随想录算法训练营第十六天(py)| 二叉树 | 104.二叉树的最大深度、111.二叉树的最小深度、222.完全二叉树的节点个数

104.二叉树的最大深度 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 思路1 迭代法 层序遍历 层序遍历的思路很简单&#xff0c;其结果本来就是按层数记录的&#xff0c;只需返回结果的长度皆可。…

【C语言回顾】联合和枚举

前言1. 联合体1.1 联合体的声明1.2 联合体的特点1.3 联合体的使用 2. 枚举2.1 枚举的声明2.2 枚举的特点2.3 枚举的使用 结语 #include<GUIQU.h> int main { 上期回顾: 【C语言回顾】结构体 个人主页&#xff1a;C_GUIQU 专栏&#xff1a;【C语言学习】 return 一键三连;…

解决法律条文的录入前判断发条冲突的需求;怎么选择NLPModel?怎么使用模型?

要在NLPModel类中实现法律条文的冲突检测功能&#xff0c;可以使用BERT模型来计算句子相似度。以下是详细的步骤&#xff0c;包括如何选择模型、训练模型以及使用模型。 选择NLP模型 根据你的需求&#xff0c;BERT&#xff08;Bidirectional Encoder Representations from Tra…

Linux多线程系列三: 生产者消费者模型,信号量使用,基于阻塞队列和环形队列的这两种生产者消费者代码的实现

Linux多线程系列三: 生产者消费者模型,信号量,基于阻塞队列和环形队列的这两种生产者消费者代码的实现 一.生产者消费者模型的理论1.现实生活中的生产者消费者模型2.多线程当中的生产者消费者模型3.理论 二.基于阻塞队列的生产者消费者模型的基础代码1.阻塞队列的介绍2.大致框架…

别说废话!说话说到点上,项目高效沟通的底层逻辑揭秘

假设你下周要在领导和同事面前汇报项目进度&#xff0c;你会怎么做&#xff1f;很多人可能会去网上搜一个项目介绍模板&#xff0c;然后按照模板来填充内容。最后&#xff0c;汇报幻灯片做了 80 页&#xff0c;自己觉得非常充实&#xff0c;但是却被领导痛批了一顿。 这样的境…

树的非递归遍历(层序)

层序是采用队列的方式来遍历的 就比如说上面这颗树 他层序的就是&#xff1a;1 24 356 void LevelOrder(BTNode* root) {Que q;QueueInit(&q);if (root){QueuePush(&q, root);}while (!QueueEmpty(&q)){BTNode* front QueueFront(&q);QueuePop(&q);print…

简析网络风险量化的价值与应用实践,如何构建网络风险预防架构

网络风险量化能够让公司董事会和高管层看清当前的网络安全风险格局&#xff1b;它还将使安全团队能够在业务需求的背景下做出网络安全决策&#xff0c;帮助组织确定哪些风险对业务构成最大的威胁&#xff0c;以及预期的经济损失将是什么。 随着网络攻击手段的日益多样化和复杂…