一篇文章通俗易懂的让你彻底理解 Java 注解
很多Java
程序员,对Java
的注解一知半解,更有甚者,有的人可能连注解是什么都不知道
本文我们用最简单的 demo
, 最通俗最短的语言,带你了解注解到底是什么?
先来简单回顾一下基础,我们知道,Java 的源文件编辑后,生成 .class 文件,
.Java
源文件,这个是源文件时期
- 源文件经过编译生成
.class
字节码文件,这个也是编译时期
.class
加载到内存中,就可以用了,这个是运行期间
如下图
记住以上知识点,下面和注解有关,我们正式来讲注解 本文将从以下 2 个方面来讲解注解
- 1 注解是什么
- 2 如何定义一个注解
- 3 如何使用注解
尤其是第3
条,很多人不理解注解,就是因为不知道如何使用注解 第3
条本文会用最简单的语言来揭示如何使用
一 注解是什么?
一句话,注解就和生活中的标签一样,比如一个人,这个人可能有 学生
标签,月光族
标签,爱抬杠
标签
二 如何定义一个注解
语法: public @interface 注解名
{ } 对的, @interface
是个关键字,记住就行了,没有为什么 定义注解就是用@interface
,后面跟上注解名
比如定义一个名字叫 info
的注解,如下 新建一个文件 info.java
,代码如下:
package com.demo; //定义了一个叫做 info 的注解 public @interface info { }
很简单吧,上面就定义了一个叫做 info
的注解,下面有2个问题来了
-
第一个: info 注解用在什么地方? 是用到
类名
上? 还是用在类的字段
上 ? 还是用在类的方法
上 ? -
第二个:info 注解生命周期(或叫保留策略,我更喜欢叫生命周期) 注解还有生命周期吗?答案是当然有了
前面说过,注解类似标签,一个人可能刚毕业,有
月光族
标签,刚毕业赚的少嘛 但是有可能过了 3,4 年,技术好了,工资涨上去了,可能就没有月光族
标签了那么标签有几个生命周期呢?就是本文开头讲的,参考上面的图 答案是:3 个 ,分别是
源文件期
,编译期
,运行期
就是说:有的注解存在于源文件期,有的标签存在于编译期,有的标签存在于运行期
::: tip 运行期的注解用的最多,本文着重讲运行期间,源文件期,编译期比较简单 看懂运行期后,可自行学习另外2个
运行期,也就是注解在运行期还存在 :::
我们接下来给 info 注解定义用在类的字段上,并且是存在于运行期间
先上代码,再解释,代码如下:
@Target(ElementType.FIELD) //注解作用在类的字段上 @Retention(RetentionPolicy.RUNTIME) //注解存在于运行期 public @interface info { }
由上面代码可以看到,出现了 @Target , @Retention 注解,那么 @Target , @Retention又是什么? 答:@Target, @Retention 是元注解,咋又出来一个元注解,可以望文生义:元就是元始的意思,最开始的意思 举个很简单的例子来帮助了解元注解
是什么
比如开发一款 IOS APP 软件,用 xcode 这个软件开发,那么 xcode软件又是用什么开发的? 定义一个注解,用元注解 是不是很类似,如下图
看过上面的图应该能理解了,什么是元注解了吧,就是为了定义注解用的,知道怎么用就行了 就比如我们开发软件,要用到各种各样的开发软件的IDE,我们不用管这些IDE软件是哪个软件开发的 我们只需要知道,元注解就相当于IDE,注解就相当于我们开发的软件,就OK了
回到上面的info
的定义,我们来解释一下 Target,Retention 这 2 个注解的用处以及能取哪些值
Target 元注解
用处:用来定义注解的用在的地方,比如是用在类上啊,还是用在字段上啊,还是用在方法上啊等 取值:我们列出几个常用的就行,其它的自行下去查义即可,如下 |取值|用在哪| |-|-|-| |ElementType.TYPE|类或者接口上| |ElementType.FIELD|类的字段上| |ElementType.METHOD|类的方法上| |ElementType.PARAMETER|方法的参数上|
Retention 元注解
用处:用来定义注解的生命周期(或叫保留策略,我更喜欢叫生命周期) 取值:就只有3个,如下 |取值|存在于哪个时期| |-|-|-| |RetentionPolicy.SOURCE|源文件期| |RetentionPolicy.CLASS|编译期| |RetentionPolicy.RUNTIME|源运行时期|
::: tip 元注解都是已经定义好的,我们只管用,只管知道怎么用就行 就是我们自定义一个注解时才用到元注解,取几个值,定义一下我们的注解用在哪些地方 存在的时期等,仅此而已 :::
通过上面的叙述,我们小小总结一下
- 注解就是类似标签一样的东西
- 注解定义是用
public @interface 注解名 { }
- 注解是有使用的地方和生命周期的
- 注解能用在类上,字段上,方法上,参数上等
- 元注解就是用来定义注解的,就像 xcode 软件是用来开发IOS 软件一样的逻辑
下面我们来讲第三点,也是最重要的一点,我们学会了自定义注解,怎么使用呢?
三 如何使用注解
注解一般是和反射一块用的,不懂反射的,不懂Java的大Class的,一定要看看下面的2篇文章 一篇文章彻底搞懂Java的大Class到底是什么 一篇文章弄懂 Java 反射的使用
我们来扩展一下上面的 info
注解,代码如下:
@Target(ElementType.FIELD) //注解作用在类的字段上 @Retention(RetentionPolicy.RUNTIME) //注解存在于运行期 public @interface info { String job(); //job属性 String comment(); //comment属性 }
对的,你又看到了注解还能定义属性,记住,就按照上面的定义就行了。 主要看怎么用
我们定义一个工人类Worker
,如下:
//工人类 public class Worker { //工人的名字 public String name; //工人简介方法,打印工作的基本信息 public void show(){ } }
很简单的一个类,我们在 name 字段上添加我们定义的info
注解,如下
public class Worker { //注解是能给属性传值的,job和comment和info定义中的相呼应,对,属性就是这样用的 @info(job = "工程师",comment = "工作很努力") public String name; public void show(){ } }
上面我们给 name 字段添加了我们自己定义的注解,并且给注解中传了工作的职位是:工程师 ,评价是:工作很努力 我们想在show()方法中,打印出工作的名字,职位,和评价
获取注解中的 job和 comment可以通过反射获取 ,注意看注释,如下
public class Worker { //注解是能给属性传的,job和comment和定义中的相呼应 @info(job = "工程师",comment = "工作很努力") public String name; public void show(){ //1 获取本类的字节码 Class clz = this.getClass(); //2 获取类中定义的字段 Field[] fields = clz.getDeclaredFields(); //3 遍历字段,看看哪个字段有info注解 for (Field field : fields){ //4 判断此字段上是否有 info 注解 info annotation = field.getAnnotation(info.class); //5 如果不为 null ,说明 field上有info注解 if (annotation != null){ //6 通过info注解,获取info注解中的 job和comment String job = annotation.job(); String comment = annotation.comment(); //7 打印出来 System.out.println("我是:" + this.name + " 我的职位是:" + job + " 我的评价是:" + comment); } } } }
通过上面可以看出,使用注解步骤如下:
- 获取类的 Class ,也就是类的字节码
- 获取类的所有字段的字码码数组
- 遍历字段
- 通过
info annotation = field.getAnnotation(info.class)
获取字段上对应的注解 - 通过注解,获取注解中传的值
我们再来写一个 main 函数,调用上面那段代码:如下
public class Demo1 { public static void main(String[] args){ Worker worker = new Worker(); worker.name = "待兔,www.helloworld.net 站长"; worker.show(); } }
打印如下:
我是:待兔,www.helloworld.net 站长
我的职位是:工程师
我的评价是:工作很努力
本文到此,几乎讲完了,注解的很多其它的东西还没有讲,不过不重要,本文最重要的让你明白什么是注解,怎么定义注解,怎么使用注解 至于注解其它的知识,比如注解怎么用在方法上,用上类上,等等,都是类似,只需要查一下就行了。 网上很多文章 ,只要能通过本文把注解弄明白了,了解注解其它的就简单了。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
推特工程师推荐的通过深度学习框架的二阶优化器
你是否曾想在TensorFlow或PyTorch编写的代码中使用二阶优化器?使用SciPy最小化来优化一个张量字典呢?如果是这样,可能需要很多麻烦的代码。对于另一种方法,请看dict-minimize包,它兼顾一切,让用户轻松优化在TensorFlow、PyTorch或JAX中实现的目标。 背景 现代深度学习框架及其内置的优化工具,都是围绕着用户想要使用随机梯度下降(SGD)或其变体(如ADAM)进行优化的假设而设计的。许多深度学习从业者甚至可能不知道在优化界有大量关于更普遍的方法的文献,这些方法在深度学习兴起之前是占主导地位的。 特别是,像L-BFGS和共轭梯度(CG)这样的方法是前深度学习时代的常用方法(有些人可能还记得使用minim.m)。那么,是什么改变了呢?在深度学习中,我们要处理巨大的数据集。因此,为训练网络获得准确的梯度需要整个时代的数据,这在计算上是不可行的。因此,我们改用做数据子采样来获得训练损失梯度的随机(无偏)估计,并使用SGD。深度学习的奇迹是,对于训练深度神经网络的权重,使用随机梯度实际上比批量优化效果更好。这是因为隐性正则化和其他原因。 然而,优化不仅仅是训...
- 下一篇
xRedis 1.5.0 发布,Redis 的 C++ 客户端库
xRedis1.5.0 版本发布! xRedis是一个 C++ 开发的 redis 客户端,是对 hiredis 的 C++ 封装,提供易用的 redis 操作接口。 功能与特点: 支持数据多节点分布存储,可自定义分片规则; 支持同时连接到每个分片的主从节点,支持主从读写分离; 支持对每个存储节点建立连接池; 支持同时连接多个数据分片集群; 支持连接到官方集群,支持自动计算节点索引位置,支持REDIS集群节点变化连接自动切换; 当官方集群节点有添加/删除/slot分布变化时,到集群的连接池会自动更新。 提供简单易用的C++接口封装,已实现大部分REDIS命令; 只依赖hiredis库; 多线程安全 支持带密码连接; 支持linux、windows平台 release 1.5.0 更新: 支持自动计算节点索引位置,支持REDIS集群节点变化连接自动切换; 当官方集群节点有添加/删除/slot分布变化时,到集群的连接池会自动更新。 修复redis官方集群连接重连接BUG。 xRedis添加内部日志模块。 更多内容见: https://github.com/0xsky/xredis
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8编译安装MySQL8.0.19
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2配置默认Tomcat设置,开启更多高级功能